开源 企业版 高校版 私有云 模力方舟 AI 队友
代码拉取完成,页面将自动刷新
开源项目 > 程序开发 > 编程语言/脚本语言 &&
捐赠
捐赠前请先登录
扫描微信二维码支付
取消
支付完成
支付提示
将跳转至支付宝完成支付
确定
取消
13 Star 69 Fork 22

johnsonyl/cpps

加入 Gitee
与超过 1400万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
已有帐号? 立即登录
文件
master
分支 (1)
标签 (4)
master
v1.0.3-beta
v1.0.3
v1.0.2
v1.0.0
master
分支 (1)
标签 (4)
master
v1.0.3-beta
v1.0.3
v1.0.2
v1.0.0
克隆/下载
克隆/下载
提示
下载代码请复制以下命令到终端执行
为确保你提交的代码身份被 Gitee 正确识别,请执行以下命令完成配置
初次使用 SSH 协议进行代码克隆、推送等操作时,需按下述提示完成 SSH 配置
1 生成 RSA 密钥
2 获取 RSA 公钥内容,并配置到 SSH公钥
在 Gitee 上使用 SVN,请访问 使用指南
使用 HTTPS 协议时,命令行会出现如下账号密码验证步骤。基于安全考虑,Gitee 建议 配置并使用私人令牌 替代登录密码进行克隆、推送等操作
Username for 'https://gitee.com': userName
Password for 'https://userName@gitee.com': # 私人令牌
master
分支 (1)
标签 (4)
master
v1.0.3-beta
v1.0.3
v1.0.2
v1.0.0
cpps
/
src
/
nedmalloc.h
cpps
/
src
/
nedmalloc.h
nedmalloc.h 59.77 KB
一键复制 编辑 原始数据 按行查看 历史
johnsonyl 提交于 2021年01月18日 22:25 +08:00 . 2021年01月18日 更新2
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362 1363 1364 1365 1366 1367 1368 1369 1370 1371 1372 1373 1374 1375 1376 1377 1378 1379 1380 1381 1382 1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 1393 1394 1395 1396 1397 1398 1399 1400 1401 1402 1403 1404 1405 1406 1407 1408 1409 1410 1411 1412 1413 1414 1415 1416 1417 1418 1419 1420 1421 1422 1423 1424 1425 1426 1427 1428 1429 1430 1431 1432 1433 1434 1435 1436 1437 1438 1439 1440 1441 1442 1443 1444 1445 1446 1447 1448 1449 1450 1451 1452 1453 1454 1455 1456 1457 1458 1459 1460 1461 1462 1463 1464 1465 1466 1467 1468 1469 1470 1471 1472 1473 1474 1475 1476 1477 1478 1479 1480 1481 1482 1483 1484 1485 1486 1487 1488 1489 1490 1491 1492 1493 1494 1495 1496 1497 1498 1499 1500 1501 1502 1503 1504 1505 1506 1507 1508 1509 1510 1511 1512 1513 1514 1515 1516 1517 1518 1519 1520 1521 1522 1523 1524 1525 1526 1527 1528 1529 1530 1531 1532 1533 1534 1535 1536 1537 1538 1539 1540 1541 1542 1543 1544 1545 1546 1547 1548 1549 1550 1551 1552 1553 1554 1555 1556 1557 1558 1559 1560 1561 1562 1563 1564 1565 1566 1567 1568 1569 1570 1571 1572 1573 1574 1575 1576 1577 1578 1579 1580 1581 1582 1583 1584 1585 1586 1587 1588 1589 1590 1591 1592 1593 1594 1595 1596 1597 1598 1599 1600 1601 1602 1603 1604 1605 1606 1607 1608 1609 1610 1611 1612 1613 1614 1615 1616 1617 1618 1619 1620
/* nedalloc, an alternative malloc implementation for multiple threads without
lock contention based on dlmalloc v2.8.4. (C) 2005-2010 Niall Douglas
Boost Software License - Version 1.0 - August 17th, 2003
Permission is hereby granted, free of charge, to any person or organization
obtaining a copy of the software and accompanying documentation covered by
this license (the "Software") to use, reproduce, display, distribute,
execute, and transmit the Software, and to prepare derivative works of the
Software, and to permit third-parties to whom the Software is furnished to
do so, all subject to the following:
The copyright notices in the Software and this entire statement, including
the above license grant, this restriction and the following disclaimer,
must be included in all copies of the Software, in whole or in part, and
all derivative works of the Software, unless such copies or derivative
works are solely in the form of machine-executable object code generated by
a source language processor.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
*/
#ifndef NEDMALLOC_H
#define NEDMALLOC_H
/*! \file nedmalloc.h
\brief Defines the functionality provided by nedalloc.
*/
/*! \mainpage
<a href="../../Readme.html">Please see the Readme.html</a>
*/
/*! \def NEDMALLOC_DEBUG
\brief Defines the assertion checking performed by nedalloc
NEDMALLOC_DEBUG can be defined to cause DEBUG to be set differently for nedmalloc
than for the rest of the build. Remember to set NDEBUG to disable all assertion
checking too.
*/
/*! \def ENABLE_LARGE_PAGES
\brief Defines whether nedalloc uses large pages (>=2Mb)
ENABLE_LARGE_PAGES enables support for requesting memory from the system in large
(typically >=2Mb) pages if the host OS supports this. These occupy just a single
TLB entry and can significantly improve performance in large working set applications.
*/
/*! \def ENABLE_FAST_HEAP_DETECTION
\brief Defines whether nedalloc takes platform specific shortcuts when detecting foreign blocks.
ENABLE_FAST_HEAP_DETECTION enables special logic to detect blocks allocated
by the system heap. This avoids 1.5%-2% overhead when checking for non-nedmalloc
blocks, but it assumes that the NT and glibc heaps function in a very specific
fashion which may not hold true across OS upgrades.
*/
/*! \def HAVE_CPP0XRVALUEREFS
\ingroup C++
\brief Enables rvalue references
Define to enable the usage of rvalue references which enables move semantics and
other things. Automatically defined if __cplusplus indicates a C++0x compiler,
otherwise you'll need to set it yourself.
*/
/*! \def HAVE_CPP0XVARIADICTEMPLATES
\ingroup C++
\brief Enables variadic templates
Define to enable the usage of variadic templates which enables the use of arbitrary
numbers of policies and other useful things. Automatically defined if __cplusplus
indicates a C++0x compiler, otherwise you'll need to set it yourself.
*/
/*! \def HAVE_CPP0XSTATICASSERT
\ingroup C++
\brief Enables static assertions
Define to enable the usage of static assertions. Automatically defined if __cplusplus
indicates a C++0x compiler, otherwise you'll need to set it yourself.
*/
/*! \def HAVE_CPP0XTYPETRAITS
\ingroup C++
\brief Enables type traits
Define to enable the usage of &lt;type_traits&gt;. Automatically defined if __cplusplus
indicates a C++0x compiler, otherwise you'll need to set it yourself.
*/
#if __cplusplus > 199711L || defined(HAVE_CPP0X) /* Do we have C++0x? */
#undef HAVE_CPP0XRVALUEREFS
#define HAVE_CPP0XRVALUEREFS 1
#undef HAVE_CPP0XVARIADICTEMPLATES
#define HAVE_CPP0XVARIADICTEMPLATES 1
#undef HAVE_CPP0XSTATICASSERT
#define HAVE_CPP0XSTATICASSERT 1
#undef HAVE_CPP0XTYPETRAITS
#define HAVE_CPP0XTYPETRAITS 1
#endif
#include <stddef.h> /* for size_t */
/*! \def NEDMALLOCEXTSPEC
\brief Defines how nedalloc's API is to be made visible.
NEDMALLOCEXTSPEC can be defined to be __declspec(dllexport) or
__attribute__ ((visibility("default"))) or whatever you like. It defaults
to extern unless NEDMALLOC_DLL_EXPORTS is set as it would be when building
nedmalloc.dll.
*/
#ifndef NEDMALLOCEXTSPEC
#ifdef NEDMALLOC_DLL_EXPORTS
#ifdef WIN32
#define NEDMALLOCEXTSPEC extern __declspec(dllexport)
#elif defined(__GNUC__)
#define NEDMALLOCEXTSPEC extern __attribute__ ((visibility("default")))
#endif
#ifndef ENABLE_TOLERANT_NEDMALLOC
#define ENABLE_TOLERANT_NEDMALLOC 1
#endif
#else
#define NEDMALLOCEXTSPEC extern
#endif
#endif
/*! \def NEDMALLOCDEPRECATED
\brief Defined to mark an API as deprecated */
#ifndef NEDMALLOCDEPRECATED
#if defined(_MSC_VER) && !defined(__GCCXML__)
#define NEDMALLOCDEPRECATED __declspec(deprecated)
#elif defined(__GNUC__) && !defined(__GCCXML__)
#define NEDMALLOCDEPRECATED __attribute ((deprecated))
#else
//! Marks a function as being deprecated
#define NEDMALLOCDEPRECATED
#endif
#endif
/*! \def RESTRICT
\brief Defined to the restrict keyword or equivalent if available */
#ifndef RESTRICT
#if __STDC_VERSION__ >= 199901L /* C99 or better */
#define RESTRICT restrict
#else
#if defined(_MSC_VER) && _MSC_VER>=1400
#define RESTRICT __restrict
#endif
#ifdef __GNUC__
#define RESTRICT __restrict
#endif
#endif
#ifndef RESTRICT
#define RESTRICT
#endif
#endif
#if defined(_MSC_VER) && _MSC_VER>=1400
#define NEDMALLOCPTRATTR __declspec(restrict)
#define NEDMALLOCNOALIASATTR __declspec(noalias)
#endif
#ifdef __GNUC__
#define NEDMALLOCPTRATTR __attribute__ ((malloc))
#endif
/*! \def NEDMALLOCPTRATTR
\brief Defined to the specifier for a pointer which points to a memory block. Like NEDMALLOCNOALIASATTR, but sadly not identical. */
#ifndef NEDMALLOCPTRATTR
#define NEDMALLOCPTRATTR
#endif
/*! \def NEDMALLOCNOALIASATTR
\brief Defined to the specifier for a pointer which does not alias any other variable. */
#ifndef NEDMALLOCNOALIASATTR
#define NEDMALLOCNOALIASATTR
#endif
/*! \def USE_MAGIC_HEADERS
\brief Defines whether nedalloc should use magic headers in foreign heap block detection
USE_MAGIC_HEADERS causes nedalloc to allocate an extra three sizeof(size_t)
to each block. nedpfree() and nedprealloc() can then automagically know when
to free a system allocated block. Enabling this typically adds 20-50% to
application memory usage, and is mandatory if USE_ALLOCATOR is not 1.
*/
#ifndef USE_MAGIC_HEADERS
#define USE_MAGIC_HEADERS 0
#endif
/*! \def USE_ALLOCATOR
\brief Defines the underlying allocator to use
USE_ALLOCATOR can be one of these settings (it defaults to 1):
0: System allocator (nedmalloc now simply acts as a threadcache) which is
very useful for testing with valgrind and Glowcode.
WARNING: Intended for DEBUG USE ONLY - not all functions work correctly.
1: dlmalloc
*/
#ifndef USE_ALLOCATOR
#define USE_ALLOCATOR 1 /* dlmalloc */
#endif
#if !USE_ALLOCATOR && !USE_MAGIC_HEADERS
#error If you are using the system allocator then you MUST use magic headers
#endif
/*! \def REPLACE_SYSTEM_ALLOCATOR
\brief Defines whether to replace the system allocator (malloc(), free() et al) with nedalloc's implementation.
REPLACE_SYSTEM_ALLOCATOR on POSIX causes nedalloc's functions to be called
malloc, free etc. instead of nedmalloc, nedfree etc. You may or may not want
this. On Windows it causes nedmalloc to patch all loaded DLLs and binaries
to replace usage of the system allocator.
Always turns on ENABLE_TOLERANT_NEDMALLOC.
*/
#ifdef REPLACE_SYSTEM_ALLOCATOR
#if USE_ALLOCATOR==0
#error Cannot combine using the system allocator with replacing the system allocator
#endif
#ifndef ENABLE_TOLERANT_NEDMALLOC
#define ENABLE_TOLERANT_NEDMALLOC 1
#endif
#ifndef WIN32 /* We have a dedicated patcher for Windows */
#define nedmalloc malloc
#define nedmalloc2 malloc2
#define nedcalloc calloc
#define nedrealloc realloc
#define nedrealloc2 realloc2
#define nedfree free
#define nedfree2 free2
#define nedmemalign memalign
#define nedmallinfo mallinfo
#define nedmallopt mallopt
#define nedmalloc_trim malloc_trim
#define nedmalloc_stats malloc_stats
#define nedmalloc_footprint malloc_footprint
#define nedindependent_calloc independent_calloc
#define nedindependent_comalloc independent_comalloc
#ifdef __GNUC__
#define nedmemsize malloc_usable_size
#endif
#endif
#endif
/*! \def ENABLE_TOLERANT_NEDMALLOC
\brief Defines whether nedalloc should check for blocks from the system allocator.
ENABLE_TOLERANT_NEDMALLOC is automatically turned on if REPLACE_SYSTEM_ALLOCATOR
is set or the Windows DLL is being built. This causes nedmalloc to detect when a
system allocator block is passed to it and to handle it appropriately. Note that
without USE_MAGIC_HEADERS there is a very tiny chance that nedmalloc will segfault
on non-Windows builds (it uses Win32 SEH to trap segfaults on Windows and there
is no comparable system on POSIX).
*/
#if defined(__cplusplus)
extern "C" {
#endif
/*! \brief Returns information about a memory pool */
struct nedmallinfo {
size_t arena; /*!< non-mmapped space allocated from system */
size_t ordblks; /*!< number of free chunks */
size_t smblks; /*!< always 0 */
size_t hblks; /*!< always 0 */
size_t hblkhd; /*!< space in mmapped regions */
size_t usmblks; /*!< maximum total allocated space */
size_t fsmblks; /*!< always 0 */
size_t uordblks; /*!< total allocated space */
size_t fordblks; /*!< total free space */
size_t keepcost; /*!< releasable (via malloc_trim) space */
};
#if defined(__cplusplus)
}
#endif
/*! \def NO_NED_NAMESPACE
\brief Defines the use of the nedalloc namespace for the C functions.
NO_NED_NAMESPACE prevents the functions from being defined in the nedalloc
namespace when in C++ (uses the global C namespace instead).
*/
/*! \def THROWSPEC
\brief Defined to throw() or noexcept(true) (as in, throws nothing) under C++, otherwise nothing.
*/
#if defined(__cplusplus)
#if !defined(NO_NED_NAMESPACE)
namespace nedalloc {
#else
extern "C" {
#endif
#if __cplusplus > 199711L
#define THROWSPEC noexcept(true)
#else
#define THROWSPEC throw()
#endif
#else
#define THROWSPEC
#endif
/* These are the global functions */
/*! \defgroup v2malloc The v2 malloc API
\warning This API is being completely retired in v1.10 beta 2 and replaced with the API
being developed for inclusion into the C1X programming language standard
For the v1.10 release which was generously sponsored by
<a href="http://www.ara.com/" target="_blank">Applied Research Associates (USA)</a>,
a new general purpose allocator API was designed which is intended to remedy many
of the long standing problems and inefficiencies introduced by the ISO C allocator
API. Internally nedalloc's implementations of nedmalloc(), nedcalloc(), nedmemalign()
and nedrealloc() call into this API:
<ul>
<li><code>void* malloc2(size_t bytes, size_t alignment, unsigned flags)</code></li>
<li><code>void* realloc2(void* mem, size_t bytes, size_t alignment, unsigned
flags)</code></li>
<li><code>void free2(void* mem, unsigned flags)</code></li>
</ul>
If nedmalloc.h is being included by C++ code, the alignment and flags parameters
default to zero which makes the new API identical to the old API (roll on the introduction
of default parameters to C!). The ability for realloc2() to take an alignment is
<em>particularly</em> useful for extending aligned vector arrays such as SSE/AVX
vector arrays. Hitherto SSE/AVX vector code had to jump through all sorts of unpleasant
hoops to maintain alignment :(.
Note that using any of these flags other than M2_ZERO_MEMORY or any alignment
other than zero inhibits the threadcache.
Currently MREMAP support is limited to Linux and Windows. Patches implementing
support for other platforms are welcome.
On Linux the non portable mremap() kernel function is currently used, so in fact
the M2_RESERVE_* options are currently ignored.
On Windows, there are two different MREMAP implementations which are chosen according
to whether a 32 bit or a 64 bit build is being performed. The 32 bit implementation
is based on Win32 file mappings where it reserves the address space within the Windows
VM system, so you can safely specify silly reservation quantities like 2Gb per block
and not exhaust local process address space. Note however that on x86 this costs
2Kb (1Kb if PAE is off) of kernel memory per Mb reserved, and as kernel memory has
a hard limit of 447Mb on x86 you will find the total address space reservable in
the system is limited. On x64, or if you define WIN32_DIRECT_USE_FILE_MAPPINGS=0
on x86, a much faster implementation of using VirtualAlloc(MEM_RESERVE) to directly
reserve the address space is used.
When using M2_RESERVE_* with realloc2(), the setting only takes effect when the
mmapped chunk has exceeded its reservation space and a new reservation space needs
to be created.
*/
#ifndef M2_FLAGS_DEFINED
#define M2_FLAGS_DEFINED
/*! \def M2_ZERO_MEMORY
\ingroup v2malloc
\brief Sets the contents of the allocated block (or any increase in the allocated
block) to zero.
Note that this zeroes only the increase from what dlmalloc thinks
the chunk's size is, so if you realloc2() a block which wasn't allocated using
malloc2() using this flag then you may have garbage just before the newly extended
space.
\li <strong>Rationale:</strong> Memory returned by the system is guaranteed to
be zero on most platforms, and hence dlmalloc knows when it can skip zeroing
memory. This improves performance.
*/
#define M2_ZERO_MEMORY (1<<0)
/*! \def M2_PREVENT_MOVE
\ingroup v2malloc
\brief Cause realloc2() to attempt to extend a block in place, but to never move
it.
\li <strong>Rationale:</strong> C++ makes almost no use of realloc(), even for
contiguous arrays such as std::vector<> because most C++ objects cannot be relocated
in memory without a copy or rvalue construction (though some clever STL implementations
specialise for Plain Old Data (POD) types, and use realloc() then and only then).
This flag allows C++ containers to speculatively try to extend in place, thus
improving performance <em>especially</em> for large allocations which will use
mmap().
*/
#define M2_PREVENT_MOVE (1<<1)
/*! \def M2_ALWAYS_MMAP
\ingroup v2malloc
\brief Always allocate as though mmap_threshold were being exceeded.
In the case of realloc2(), note that setting this bit will not necessarily mmap a chunk
which isn't already mmapped, but it will force a mmapped chunk if new memory
needs allocating.
\li <strong>Rationale:</strong> If you know that an array you are allocating
is going to be repeatedly extended up into the hundred of kilobytes range, then
you can avoid the constant memory copying into larger blocks by specifying this
flag at the beginning along with one of the M2_RESERVE_* flags below. This can
<strong>greatly</strong> improve performance for large arrays.
*/
#define M2_ALWAYS_MMAP (1<<2)
#define M2_RESERVED1 (1<<3)
#define M2_RESERVED2 (1<<4)
#define M2_RESERVED3 (1<<5)
#define M2_RESERVED4 (1<<6)
#define M2_RESERVED5 (1<<7)
#define M2_RESERVE_ISMULTIPLIER (1<<15)
/* 7 bits is given to the address reservation specifier.
This lets you set a multiplier (bit 15 set) or a 1<< shift value.
*/
#define M2_RESERVE_MASK 0x00007f00
/*! \def M2_RESERVE_MULT(n)
\ingroup v2malloc
\brief Reserve n times as much address space such that mmapped realloc2(size <=
n * original size) avoids memory copying and hence is much faster.
*/
#define M2_RESERVE_MULT(n) (M2_RESERVE_ISMULTIPLIER|(((n)<<8)&M2_RESERVE_MASK))
/*! \def M2_RESERVE_SHIFT(n)
\ingroup v2malloc
\brief Reserve (1<<n) bytes of address space such that mmapped realloc2(size <=
(1<<n)) avoids memory copying and hence is much faster.
*/
#define M2_RESERVE_SHIFT(n) (((n)<<8)&M2_RESERVE_MASK)
#define M2_FLAGS_MASK 0x0000ffff
#define M2_CUSTOM_FLAGS_BEGIN (1<<16)
#define M2_CUSTOM_FLAGS_MASK 0xffff0000
/*! \def NM_SKIP_TOLERANCE_CHECKS
\ingroup v2malloc
\brief Causes nedmalloc to not inspect the block being passed to see if it belongs
to the system allocator. Can improve speed by up to 10%.
*/
#define NM_SKIP_TOLERANCE_CHECKS (1<<31)
#endif /* M2_FLAGS_DEFINED */
#if defined(__cplusplus)
/*! \brief Gets the usable size of an allocated block.
Note this will always be bigger than what was
asked for due to rounding etc. Optionally returns 1 in isforeign if the block came from the
system allocator - note that there is a small (>0.01%) but real chance of segfault on non-Windows
systems when passing non-nedmalloc blocks if you don't use USE_MAGIC_HEADERS.
*/
NEDMALLOCEXTSPEC NEDMALLOCNOALIASATTR size_t nedblksize(int *RESTRICT isforeign, void *RESTRICT mem, unsigned flags=0) THROWSPEC;
#else
NEDMALLOCEXTSPEC NEDMALLOCNOALIASATTR size_t nedblksize(int *RESTRICT isforeign, void *RESTRICT mem, unsigned flags) THROWSPEC;
#endif
/*! \brief Identical to nedblksize() except without the isforeign */
NEDMALLOCEXTSPEC NEDMALLOCNOALIASATTR size_t nedmemsize(void *RESTRICT mem) THROWSPEC;
/*! \brief Equivalent to nedpsetvalue((nedpool *) 0, v) */
NEDMALLOCEXTSPEC NEDMALLOCNOALIASATTR void nedsetvalue(void *v) THROWSPEC;
/*! \brief Equivalent to nedpmalloc2((nedpool *) 0, size, 0, 0) */
NEDMALLOCEXTSPEC NEDMALLOCNOALIASATTR NEDMALLOCPTRATTR void * nedmalloc(size_t size) THROWSPEC;
/*! \brief Equivalent to nedpmalloc2((nedpool *) 0, no*size, 0, M2_ZERO_MEMORY) */
NEDMALLOCEXTSPEC NEDMALLOCNOALIASATTR NEDMALLOCPTRATTR void * nedcalloc(size_t no, size_t size) THROWSPEC;
/*! \brief Equivalent to nedprealloc2((nedpool *) 0, size, mem, size, 0, M2_RESERVE_MULT(8)) */
NEDMALLOCEXTSPEC NEDMALLOCNOALIASATTR NEDMALLOCPTRATTR void * nedrealloc(void *mem, size_t size) THROWSPEC;
/*! \brief Equivalent to nedpfree2((nedpool *) 0, mem, 0) */
NEDMALLOCEXTSPEC NEDMALLOCNOALIASATTR void nedfree(void *mem) THROWSPEC;
/*! \brief Equivalent to nedpmalloc2((nedpool *) 0, size, alignment, 0) */
NEDMALLOCEXTSPEC NEDMALLOCNOALIASATTR NEDMALLOCPTRATTR void * nedmemalign(size_t alignment, size_t bytes) THROWSPEC;
#if defined(__cplusplus)
/*! \ingroup v2malloc
\brief Equivalent to nedpmalloc2((nedpool *) 0, size, alignment, flags) */
NEDMALLOCEXTSPEC NEDMALLOCNOALIASATTR NEDMALLOCPTRATTR void * nedmalloc2(size_t size, size_t alignment=0, unsigned flags=0) THROWSPEC;
/*! \ingroup v2malloc
\brief Equivalent to nedprealloc2((nedpool *) 0, mem, size, alignment, flags) */
NEDMALLOCEXTSPEC NEDMALLOCNOALIASATTR NEDMALLOCPTRATTR void * nedrealloc2(void *mem, size_t size, size_t alignment=0, unsigned flags=0) THROWSPEC;
/*! \ingroup v2malloc
\brief Equivalent to nedpfree2((nedpool *) 0, mem, flags) */
NEDMALLOCEXTSPEC NEDMALLOCNOALIASATTR void nedfree2(void *mem, unsigned flags=0) THROWSPEC;
#else
NEDMALLOCEXTSPEC NEDMALLOCNOALIASATTR NEDMALLOCPTRATTR void * nedmalloc2(size_t size, size_t alignment, unsigned flags) THROWSPEC;
NEDMALLOCEXTSPEC NEDMALLOCNOALIASATTR NEDMALLOCPTRATTR void * nedrealloc2(void *mem, size_t size, size_t alignment, unsigned flags) THROWSPEC;
NEDMALLOCEXTSPEC NEDMALLOCNOALIASATTR void nedfree2(void *mem, unsigned flags) THROWSPEC;
#endif
/*! \brief Equivalent to nedpmallinfo((nedpool *) 0) */
NEDMALLOCEXTSPEC NEDMALLOCNOALIASATTR struct nedmallinfo nedmallinfo(void) THROWSPEC;
/*! \brief Equivalent to nedpmallopt((nedpool *) 0, parno, value) */
NEDMALLOCEXTSPEC NEDMALLOCNOALIASATTR int nedmallopt(int parno, int value) THROWSPEC;
/*! \brief Returns the internal allocation granularity and the magic header XOR used for internal consistency checks. */
NEDMALLOCEXTSPEC NEDMALLOCNOALIASATTR void* nedmalloc_internals(size_t *granularity, size_t *magic) THROWSPEC;
/*! \brief Equivalent to nedpmalloc_trim((nedpool *) 0, pad) */
NEDMALLOCEXTSPEC NEDMALLOCNOALIASATTR int nedmalloc_trim(size_t pad) THROWSPEC;
/*! \brief Equivalent to nedpmalloc_stats((nedpool *) 0) */
NEDMALLOCEXTSPEC void nedmalloc_stats(void) THROWSPEC;
/*! \brief Equivalent to nedpmalloc_footprint((nedpool *) 0) */
NEDMALLOCEXTSPEC NEDMALLOCNOALIASATTR size_t nedmalloc_footprint(void) THROWSPEC;
/*! \brief Equivalent to nedpindependent_calloc((nedpool *) 0, elemsno, elemsize, chunks) */
NEDMALLOCEXTSPEC NEDMALLOCNOALIASATTR NEDMALLOCPTRATTR void **nedindependent_calloc(size_t elemsno, size_t elemsize, void **chunks) THROWSPEC;
/*! \brief Equivalent to nedpindependent_comalloc((nedpool *) 0, elems, sizes, chunks) */
NEDMALLOCEXTSPEC NEDMALLOCNOALIASATTR NEDMALLOCPTRATTR void **nedindependent_comalloc(size_t elems, size_t *sizes, void **chunks) THROWSPEC;
/*! \brief Destroys the system memory pool used by the functions above.
Useful for when you have nedmalloc in a DLL you're about to unload.
If you call ANY nedmalloc functions after calling this you will
get a fatal exception!
*/
NEDMALLOCEXTSPEC void neddestroysyspool() THROWSPEC;
/*! \brief A nedpool type */
struct nedpool_t;
/*! \brief A nedpool type */
typedef struct nedpool_t nedpool;
/*! \brief Creates a memory pool for use with the nedp* functions below.
Capacity is how much to allocate immediately (if you know you'll be allocating a lot
of memory very soon) which you can leave at zero. Threads specifies how many threads
will *normally* be accessing the pool concurrently. Setting this to zero means it
extends on demand, but be careful of this as it can rapidly consume system resources
where bursts of concurrent threads use a pool at once.
*/
NEDMALLOCEXTSPEC NEDMALLOCNOALIASATTR NEDMALLOCPTRATTR nedpool *nedcreatepool(size_t capacity, int threads) THROWSPEC;
/*! \brief Destroys a memory pool previously created by nedcreatepool().
*/
NEDMALLOCEXTSPEC void neddestroypool(nedpool *p) THROWSPEC;
/*! \brief Returns a zero terminated snapshot of threadpools existing at the time of call.
Call nedfree() on the returned list when you are done. Returns zero if there is only the
system pool in existence.
*/
NEDMALLOCEXTSPEC nedpool **nedpoollist() THROWSPEC;
/*! \brief Sets a value to be associated with a pool.
You can retrieve this value by passing any memory block allocated from that pool.
*/
NEDMALLOCEXTSPEC void nedpsetvalue(nedpool *p, void *v) THROWSPEC;
/*! \brief Gets a previously set value using nedpsetvalue() or zero if memory is unknown.
Optionally can also retrieve pool. You can detect an unknown block by the return
being zero and *p being unmodifed.
*/
NEDMALLOCEXTSPEC void *nedgetvalue(nedpool **p, void *mem) THROWSPEC;
/*! \brief Trims the thread cache for the calling thread, returning any existing cache
data to the central pool.
Remember to ALWAYS call with zero if you used the system pool. Setting disable to
non-zero replicates neddisablethreadcache().
*/
NEDMALLOCEXTSPEC void nedtrimthreadcache(nedpool *p, int disable) THROWSPEC;
/*! \brief Disables the thread cache for the calling thread, returning any existing cache
data to the central pool.
Remember to ALWAYS call with zero if you used the system pool.
*/
NEDMALLOCEXTSPEC void neddisablethreadcache(nedpool *p) THROWSPEC;
/*! \brief Releases all memory in all threadcaches in the pool, and writes all
accumulated memory operations to the log if enabled.
You can pass zero for filepath to use the compiled default, or else a char[MAX_PATH]
containing the path you wish to use for the log file. The log file is always
appended to if it already exists. After writing the logs, the logging ability
is disabled for that pool.
\warning Do NOT call this if the pool is in use - this call is NOT threadsafe.
*/
NEDMALLOCEXTSPEC size_t nedflushlogs(nedpool *p, char *filepath) THROWSPEC;
/*! \brief Equivalent to nedpmalloc2(p, size, 0, 0) */
NEDMALLOCEXTSPEC NEDMALLOCNOALIASATTR NEDMALLOCPTRATTR void * nedpmalloc(nedpool *p, size_t size) THROWSPEC;
/*! \brief Equivalent to nedpmalloc2(p, no*size, 0, M2_ZERO_MEMORY) */
NEDMALLOCEXTSPEC NEDMALLOCNOALIASATTR NEDMALLOCPTRATTR void * nedpcalloc(nedpool *p, size_t no, size_t size) THROWSPEC;
/*! \brief Equivalent to nedprealloc2(p, mem, size, 0, M2_RESERVE_MULT(8)) */
NEDMALLOCEXTSPEC NEDMALLOCNOALIASATTR NEDMALLOCPTRATTR void * nedprealloc(nedpool *p, void *mem, size_t size) THROWSPEC;
/*! \brief Equivalent to nedpfree2(p, mem, 0) */
NEDMALLOCEXTSPEC NEDMALLOCNOALIASATTR void nedpfree(nedpool *p, void *mem) THROWSPEC;
/*! \brief Equivalent to nedpmalloc2(p, bytes, alignment, 0) */
NEDMALLOCEXTSPEC NEDMALLOCNOALIASATTR NEDMALLOCPTRATTR void * nedpmemalign(nedpool *p, size_t alignment, size_t bytes) THROWSPEC;
#if defined(__cplusplus)
/*! \ingroup v2malloc
\brief Allocates a block of memory sized \em size from pool \em p, aligned to \em alignment and according to the flags \em flags.
*/
NEDMALLOCEXTSPEC NEDMALLOCNOALIASATTR NEDMALLOCPTRATTR void * nedpmalloc2(nedpool *p, size_t size, size_t alignment=0, unsigned flags=0) THROWSPEC;
/*! \ingroup v2malloc
\brief Resizes the block of memory at \em mem in pool \em p to size \em size, aligned to \em alignment and according to the flags \em flags.
*/
NEDMALLOCEXTSPEC NEDMALLOCNOALIASATTR NEDMALLOCPTRATTR void * nedprealloc2(nedpool *p, void *mem, size_t size, size_t alignment=0, unsigned flags=0) THROWSPEC;
/*! \brief Frees the block \em mem from the pool \em p according to flags \em flags. */
NEDMALLOCEXTSPEC NEDMALLOCNOALIASATTR void nedpfree2(nedpool *p, void *mem, unsigned flags=0) THROWSPEC;
#else
NEDMALLOCEXTSPEC NEDMALLOCNOALIASATTR NEDMALLOCPTRATTR void * nedpmalloc2(nedpool *p, size_t size, size_t alignment, unsigned flags) THROWSPEC;
NEDMALLOCEXTSPEC NEDMALLOCNOALIASATTR NEDMALLOCPTRATTR void * nedprealloc2(nedpool *p, void *mem, size_t size, size_t alignment, unsigned flags) THROWSPEC;
NEDMALLOCEXTSPEC NEDMALLOCNOALIASATTR void nedpfree2(nedpool *p, void *mem, unsigned flags) THROWSPEC;
#endif
/*! \brief Returns information about the memory pool */
NEDMALLOCEXTSPEC struct nedmallinfo nedpmallinfo(nedpool *p) THROWSPEC;
/*! \brief Changes the operational parameters of the memory pool */
NEDMALLOCEXTSPEC int nedpmallopt(nedpool *p, int parno, int value) THROWSPEC;
/*! \brief Tries to release as much free memory back to the system as possible, leaving \em pad remaining per threadpool. */
NEDMALLOCEXTSPEC int nedpmalloc_trim(nedpool *p, size_t pad) THROWSPEC;
/*! \brief Prints some operational statistics to stdout. */
NEDMALLOCEXTSPEC void nedpmalloc_stats(nedpool *p) THROWSPEC;
/*! \brief Returns how much memory is currently in use by the memory pool */
NEDMALLOCEXTSPEC size_t nedpmalloc_footprint(nedpool *p) THROWSPEC;
/*! \brief Returns a series of guaranteed consecutive cleared memory allocations.
independent_calloc is similar to calloc, but instead of returning a
single cleared space, it returns an array of pointers to n_elements
independent elements that can hold contents of size elem_size, each
of which starts out cleared, and can be independently freed,
realloc'ed etc. The elements are guaranteed to be adjacently
allocated (this is not guaranteed to occur with multiple callocs or
mallocs), which may also improve cache locality in some
applications.
The "chunks" argument is optional (i.e., may be null, which is
probably the most typical usage). If it is null, the returned array
is itself dynamically allocated and should also be freed when it is
no longer needed. Otherwise, the chunks array must be of at least
n_elements in length. It is filled in with the pointers to the
chunks.
In either case, independent_calloc returns this pointer array, or
null if the allocation failed. If n_elements is zero and "chunks"
is null, it returns a chunk representing an array with zero elements
(which should be freed if not wanted).
Each element must be individually freed when it is no longer
needed. If you'd like to instead be able to free all at once, you
should instead use regular calloc and assign pointers into this
space to represent elements. (In this case though, you cannot
independently free elements.)
independent_calloc simplifies and speeds up implementations of many
kinds of pools. It may also be useful when constructing large data
structures that initially have a fixed number of fixed-sized nodes,
but the number is not known at compile time, and some of the nodes
may later need to be freed. For example:
struct Node { int item; struct Node* next; };
struct Node* build_list() {
struct Node** pool;
int n = read_number_of_nodes_needed();
if (n <= 0) return 0;
pool = (struct Node**)(independent_calloc(n, sizeof(struct Node), 0);
if (pool == 0) die();
// organize into a linked list...
struct Node* first = pool[0];
for (i = 0; i < n-1; ++i)
pool[i]->next = pool[i+1];
free(pool); // Can now free the array (or not, if it is needed later)
return first;
}
*/
NEDMALLOCEXTSPEC NEDMALLOCNOALIASATTR NEDMALLOCPTRATTR void **nedpindependent_calloc(nedpool *p, size_t elemsno, size_t elemsize, void **chunks) THROWSPEC;
/*! \brief Returns a series of guaranteed consecutive allocations.
independent_comalloc allocates, all at once, a set of n_elements
chunks with sizes indicated in the "sizes" array. It returns
an array of pointers to these elements, each of which can be
independently freed, realloc'ed etc. The elements are guaranteed to
be adjacently allocated (this is not guaranteed to occur with
multiple callocs or mallocs), which may also improve cache locality
in some applications.
The "chunks" argument is optional (i.e., may be null). If it is null
the returned array is itself dynamically allocated and should also
be freed when it is no longer needed. Otherwise, the chunks array
must be of at least n_elements in length. It is filled in with the
pointers to the chunks.
In either case, independent_comalloc returns this pointer array, or
null if the allocation failed. If n_elements is zero and chunks is
null, it returns a chunk representing an array with zero elements
(which should be freed if not wanted).
Each element must be individually freed when it is no longer
needed. If you'd like to instead be able to free all at once, you
should instead use a single regular malloc, and assign pointers at
particular offsets in the aggregate space. (In this case though, you
cannot independently free elements.)
independent_comallac differs from independent_calloc in that each
element may have a different size, and also that it does not
automatically clear elements.
independent_comalloc can be used to speed up allocation in cases
where several structs or objects must always be allocated at the
same time. For example:
struct Head { ... }
struct Foot { ... }
void send_message(char* msg) {
int msglen = strlen(msg);
size_t sizes[3] = { sizeof(struct Head), msglen, sizeof(struct Foot) };
void* chunks[3];
if (independent_comalloc(3, sizes, chunks) == 0)
die();
struct Head* head = (struct Head*)(chunks[0]);
char* body = (char*)(chunks[1]);
struct Foot* foot = (struct Foot*)(chunks[2]);
// ...
}
In general though, independent_comalloc is worth using only for
larger values of n_elements. For small values, you probably won't
detect enough difference from series of malloc calls to bother.
Overuse of independent_comalloc can increase overall memory usage,
since it cannot reuse existing noncontiguous small chunks that
might be available for some of the elements.
*/
NEDMALLOCEXTSPEC NEDMALLOCNOALIASATTR NEDMALLOCPTRATTR void **nedpindependent_comalloc(nedpool *p, size_t elems, size_t *sizes, void **chunks) THROWSPEC;
#if defined(__cplusplus)
} /* namespace or extern "C" */
#include <new>
#include <memory>
#ifdef HAVE_CPP0XTYPETRAITS
#include <type_traits>
#endif
// Touch into existence for future platforms
namespace std { namespace tr1 { } }
/*! \defgroup C++ C++ language support
Thanks to the generous support of Applied Research Associates (USA), nedalloc has extensive
C++ language support which uses C++ metaprogramming techniques to provide a policy driven
STL container reimplementor. The metaprogramming silently overrides or replaces the STL implementation
on your system (MSVC and GCC are the two currently supported) to \b substantially improve
the performance of STL containers by making use of nedalloc's additional features.
Sounds difficult to use? Not really. Simply do this:
\code
using namespace nedalloc;
typedef nedallocatorise<std::vector, unsigned int,
nedpolicy::typeIsPOD<true>::policy,
nedpolicy::mmap<>::policy,
nedpolicy::reserveN<26>::policy // 1<<26 = 64Mb. 10,000,000 * sizeof(unsigned int) = 38Mb.
>::value myvectortype;
myvectortype a;
for(int n=0; n<10000000; n++)
a.push_back(n);
\endcode
The metaprogramming requires a new C++ compiler (> year 2008), and it will readily make use
of a C++0x compiler where it will use rvalue referencing, variadic templates, type traits and more.
Visual Studio 2008 or later is sufficent, as is GCC v4.4 or later.
nedalloc's metaprogramming is designed to be extensible, so the rest of this page is intended for those
wishing to customise the metaprogramming. If you simply wish to know how to use the
nedalloc::nedallocator STL allocator or the nedalloc::nedallocatorise STL reimplementor, please refer
to test.cpp which gives several examples of usage.
<h2>Extending the metaprogramming:</h2>
A nedallocator policy looks as follows:
\code
namespace nedpolicy {
template<size_t size, size_t alignment> struct sizedalign
{
template<class Base> class policy : public Base
{
template<class implementation> friend class nedallocatorI::baseimplementation;
protected:
size_t policy_alignment(size_t bytes) const
{
return (bytes < size) ? alignment : 0;
}
};
};
}
\endcode
The policy above implements a size based alignment, so if the block being allocated is
less than \em size then it causes \em alignment to be used, otherwise it does not align.
The sizedalign struct is merely a template parameter encapsulator used to capture
additional parameters, so the real policy is in fact the class policy held within in.
If you did not need to specify any additional parameters e.g. if you were defining
policy_nedpool(), then you would directly define a policy returning your nedpool and pass
it directly to nedallocator<>.
The primary policy functions which are intended to be overridden are listed in
nedalloc::nedallocatorI::baseimplementation in nedmalloc.h and are prefixed by "policy_".
However, there is absolutely no reason why the meatier functions such as
nedalloc::nedallocatorI::baseimplementation::allocate() cannot be overriden, and indeed
some of the policies defined in nedmalloc.h do just that.
Policy composition is handled by a dedicated recursive variadic template called
nedalloc::nedallocatorI::policycompositor. If you have \em really specialised needs, you
can partially specialise this class to make it do all sorts of interesting things - hence
its separation into its own class.
*/
/*! \brief The nedalloc namespace */
namespace nedalloc {
/*! \def NEDSTATIC_ASSERT(expr, msg)
\brief Generates a static assertion if (expr)==0 at compile time.
Make SURE your message contains no spaces or anything else which would make it an invalid
variable name.
*/
#ifndef HAVE_CPP0XSTATICASSERT
template<bool> struct StaticAssert;
template<> struct StaticAssert<true>
{
StaticAssert() { }
};
#define NEDSTATIC_ASSERT(expr, msg) \
nedalloc::StaticAssert<(expr)!=0> ERROR_##msg
#else
#define NEDSTATIC_ASSERT(expr, msg) static_assert((expr)!=0, #msg )
#endif
/*! \brief The policy namespace in which all nedallocator policies live. */
namespace nedpolicy {
/*! \class empty
\ingroup C++
\brief An empty policy which does nothing.
*/
template<class Base> class empty : public Base
{
};
}
/*! \brief The implementation namespace where the internals live. */
namespace nedallocatorI
{
using namespace std;
using namespace tr1;
/* Roll on variadic templates is all I can say! */
#ifdef HAVE_CPP0XVARIADICTEMPLATES
template<class Impl, template<class> class... policies> class policycompositor;
template<class Impl, template<class> class A, template<class> class... policies> class policycompositor<Impl, A, policies...>
{
typedef policycompositor<Impl, policies...> temp;
public:
typedef A<typename temp::value> value;
};
#else
template<class Impl,
template<class> class A=nedpolicy::empty,
template<class> class B=nedpolicy::empty,
template<class> class C=nedpolicy::empty,
template<class> class D=nedpolicy::empty,
template<class> class E=nedpolicy::empty,
template<class> class F=nedpolicy::empty,
template<class> class G=nedpolicy::empty,
template<class> class H=nedpolicy::empty,
template<class> class I=nedpolicy::empty,
template<class> class J=nedpolicy::empty,
template<class> class K=nedpolicy::empty,
template<class> class L=nedpolicy::empty,
template<class> class M=nedpolicy::empty,
template<class> class N=nedpolicy::empty,
template<class> class O=nedpolicy::empty
> class policycompositor
{
typedef policycompositor<Impl, B, C, D, E, F, G, H, I, J, K, L, M, N, O> temp;
public:
typedef A<typename temp::value> value;
};
#endif
template<class Impl> class policycompositor<Impl>
{
public:
typedef Impl value;
};
}
template<typename T,
#ifdef HAVE_CPP0XVARIADICTEMPLATES
template<class> class... policies
#else
template<class> class policy1=nedpolicy::empty,
template<class> class policy2=nedpolicy::empty,
template<class> class policy3=nedpolicy::empty,
template<class> class policy4=nedpolicy::empty,
template<class> class policy5=nedpolicy::empty,
template<class> class policy6=nedpolicy::empty,
template<class> class policy7=nedpolicy::empty,
template<class> class policy8=nedpolicy::empty,
template<class> class policy9=nedpolicy::empty,
template<class> class policy10=nedpolicy::empty,
template<class> class policy11=nedpolicy::empty,
template<class> class policy12=nedpolicy::empty,
template<class> class policy13=nedpolicy::empty,
template<class> class policy14=nedpolicy::empty,
template<class> class policy15=nedpolicy::empty
#endif
> class nedallocator;
namespace nedallocatorI
{
/*! \brief The base implementation class */
template<class implementation> class baseimplementation
{
//NEDSTATIC_ASSERT(false, Bad_policies_specified);
};
/*! \brief The base implementation class */
template<typename T,
#ifdef HAVE_CPP0XVARIADICTEMPLATES
template<class> class... policies
#else
template<class> class policy1,
template<class> class policy2,
template<class> class policy3,
template<class> class policy4,
template<class> class policy5,
template<class> class policy6,
template<class> class policy7,
template<class> class policy8,
template<class> class policy9,
template<class> class policy10,
template<class> class policy11,
template<class> class policy12,
template<class> class policy13,
template<class> class policy14,
template<class> class policy15
#endif
> class baseimplementation<nedallocator<T,
#ifdef HAVE_CPP0XVARIADICTEMPLATES
policies...
#else
policy1, policy2, policy3, policy4, policy5,
policy6, policy7, policy8, policy9, policy10,
policy11, policy12, policy13, policy14, policy15
#endif
> >
{
protected:
//! \brief The most derived nedallocator implementation type
typedef nedallocator<T,
#ifdef HAVE_CPP0XVARIADICTEMPLATES
policies...
#else
policy1, policy2, policy3, policy4, policy5,
policy6, policy7, policy8, policy9, policy10,
policy11, policy12, policy13, policy14, policy15
#endif
> implementationType;
//! \brief Returns a this for the most derived nedallocator implementation type
implementationType *_this() { return static_cast<implementationType *>(this); }
//! \brief Returns a this for the most derived nedallocator implementation type
const implementationType *_this() const { return static_cast<const implementationType *>(this); }
//! \brief Specifies the nedpool to use. Defaults to zero (the system pool).
nedpool *policy_nedpool(size_t bytes) const
{
return 0;
}
//! \brief Specifies the granularity to use. Defaults to \em bytes (no granularity).
size_t policy_granularity(size_t bytes) const
{
return bytes;
}
//! \brief Specifies the alignment to use. Defaults to zero (no alignment).
size_t policy_alignment(size_t bytes) const
{
return 0;
}
//! \brief Specifies the flags to use. Defaults to zero (no flags).
unsigned policy_flags(size_t bytes) const
{
return 0;
}
//! \brief Specifies what to do when the allocation fails. Defaults to throwing std::bad_alloc.
void policy_throwbadalloc(size_t bytes) const
{
throw std::bad_alloc();
}
//! \brief Specifies if the type is POD. Is std::is_trivially_copyable<T>::value on C++0x compilers, otherwise false.
static const bool policy_typeIsPOD=
#ifdef HAVE_CPP0XTYPETRAITS
#if defined(__GNUC__) && (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) < 40900
is_pod<T>::value;
#else
is_trivially_copyable<T>::value;
#endif
#else
false;
#endif
public:
typedef T *pointer;
typedef const T *const_pointer;
typedef T &reference;
typedef const T &const_reference;
typedef T value_type;
typedef size_t size_type;
typedef ptrdiff_t difference_type;
T *address(T &r) const { return &r; }
const T *address(const T &s) const { return &s; }
size_t max_size() const { return (static_cast<size_t>(0) - static_cast<size_t>(1)) / sizeof(T); }
bool operator!=(const baseimplementation &other) const { return !(*this == other); }
bool operator==(const baseimplementation &other) const { return true; }
void construct(T *const p, const T &t) const {
void *const _p = static_cast<void *>(p);
new (_p) T(t);
}
void destroy(T *const p) const {
p->~T();
}
baseimplementation() { }
baseimplementation(const baseimplementation &) { }
#ifdef HAVE_CPP0XRVALUEREFS
baseimplementation(baseimplementation &&) { }
#endif
template<typename U> struct rebind {
typedef nedallocator<U,
#ifdef HAVE_CPP0XVARIADICTEMPLATES
policies...
#else
policy1, policy2, policy3, policy4, policy5,
policy6, policy7, policy8, policy9, policy10,
policy11, policy12, policy13, policy14, policy15
#endif
> other;
};
template<typename U> baseimplementation(const nedallocator<U,
#ifdef HAVE_CPP0XVARIADICTEMPLATES
policies...
#else
policy1, policy2, policy3, policy4, policy5,
policy6, policy7, policy8, policy9, policy10,
policy11, policy12, policy13, policy14, policy15
#endif
> &) { }
T *allocate(const size_t n) const {
// Leave these spelled out to aid debugging
const size_t t_size = sizeof(T);
size_t size = _this()->policy_granularity(n*t_size);
nedpool *pool = _this()->policy_nedpool(size);
size_t alignment = _this()->policy_alignment(size);
unsigned flags = _this()->policy_flags(size);
void *ptr = nedpmalloc2(pool, size, alignment, flags);
if(!ptr)
_this()->policy_throwbadalloc(size);
return static_cast<T *>(ptr);
}
void deallocate(T *p, const size_t n) const {
nedpfree(0/*not needed*/, p);
}
template<typename U> T *allocate(const size_t n, const U * /* hint */) const {
return allocate(n);
}
private:
baseimplementation &operator=(const baseimplementation &);
};
}
namespace nedpolicy
{
/*! \class granulate
\ingroup C++
\brief A policy setting the granularity of the allocated memory.
Memory is sized according to (size+granularity-1) & ~(granularity-1).
In other words, granularity \b must be a power of two.
*/
template<size_t granularity> struct granulate
{
template<class Base> class policy : public Base
{
template<class implementation> friend class nedallocatorI::baseimplementation;
protected:
size_t policy_granularity(size_t bytes) const
{
return (bytes+granularity-1) & ~(granularity-1);
}
};
};
/*! \class align
\ingroup C++
\brief A policy setting the alignment of the allocated memory.
*/
template<size_t alignment> struct align
{
template<class Base> class policy : public Base
{
template<class implementation> friend class nedallocatorI::baseimplementation;
protected:
size_t policy_alignment(size_t bytes) const
{
return alignment;
}
};
};
/*! \class zero
\ingroup C++
\brief A policy causing the zeroing of the allocated memory.
*/
template<bool dozero=true> struct zero
{
template<class Base> class policy : public Base
{
template<class implementation> friend class nedallocatorI::baseimplementation;
protected:
unsigned policy_flags(size_t bytes) const
{
return dozero ? Base::policy_flags(bytes)|M2_ZERO_MEMORY : Base::policy_flags(bytes);
}
};
};
/*! \class preventmove
\ingroup C++
\brief A policy preventing the moving of the allocated memory.
*/
template<bool doprevent=true> struct preventmove
{
template<class Base> class policy : public Base
{
template<class implementation> friend class nedallocatorI::baseimplementation;
protected:
unsigned policy_flags(size_t bytes) const
{
return doprevent ? Base::policy_flags(bytes)|M2_PREVENT_MOVE : Base::policy_flags(bytes);
}
};
};
/*! \class mmap
\ingroup C++
\brief A policy causing the mmapping of the allocated memory.
*/
template<bool dommap=true> struct mmap
{
template<class Base> class policy : public Base
{
template<class implementation> friend class nedallocatorI::baseimplementation;
protected:
unsigned policy_flags(size_t bytes) const
{
return dommap ? Base::policy_flags(bytes)|M2_ALWAYS_MMAP : Base::policy_flags(bytes);
}
};
};
/*! \class reserveX
\ingroup C++
\brief A policy causing the address reservation of X times the allocated memory.
*/
template<size_t X> struct reserveX
{
template<class Base> class policy : public Base
{
template<class implementation> friend class nedallocatorI::baseimplementation;
protected:
unsigned policy_flags(size_t bytes) const
{
return Base::policy_flags(bytes)|M2_RESERVE_MULT(X);
}
};
};
/*! \class reserveN
\ingroup C++
\brief A policy causing the address reservation of (1<<N) bytes of memory.
*/
template<size_t N> struct reserveN
{
template<class Base> class policy : public Base
{
template<class implementation> friend class nedallocatorI::baseimplementation;
protected:
unsigned policy_flags(size_t bytes) const
{
return Base::policy_flags(bytes)|M2_RESERVE_SHIFT(N);
}
};
};
/*! \class badalloc
\ingroup C++
\brief A policy specifying what to throw when an allocation failure occurs.
A type specialisation exists for badalloc<void> which is equivalent to new(nothrow)
i.e. return zero and don't throw anything.
*/
template<typename T> struct badalloc
{
template<class Base> class policy : public Base
{
template<class implementation> friend class nedallocatorI::baseimplementation;
protected:
void policy_throwbadalloc(size_t bytes) const
{
throw T();
}
};
};
template<> struct badalloc<void>
{
template<class Base> class policy : public Base
{
template<class implementation> friend class nedallocatorI::baseimplementation;
protected:
void policy_throwbadalloc(size_t bytes) const
{
}
};
};
/*! \class typeIsPOD
\ingroup C++
\brief A policy forcing the treatment of the type as Plain Old Data (POD)
On C++0x compilers, the &lt;type_traits&gt; is_trivially_copyable<type>::value is used by default.
When treated as POD, memcpy() is used instead
of copy construction and realloc() is permitted to move the memory contents when
resizing.
*/
template<bool ispod> struct typeIsPOD
{
template<class Base> class policy : public Base
{
template<class implementation> friend class nedallocatorI::baseimplementation;
protected:
static const bool policy_typeIsPOD=ispod;
};
};
}
/*! \class nedallocator
\ingroup C++
\brief A policy driven STL allocator which uses nedmalloc
One of the lesser known features of STL container classes is their ability to take
an allocator implementation class, so where you had std::vector<Foo> you can now
have std::vector<Foo, nedalloc::nedallocator< std::vector<Foo> > such that
std::vector<> will now use nedalloc as the policy specifies.
You <b>almost certainly</b> don't want to use this directly except in the naive
case. See nedalloc::nedallocatorise to see what I mean.
*/
template<typename T,
#ifdef HAVE_CPP0XVARIADICTEMPLATES
template<class> class... policies
#else
template<class> class policy1,
template<class> class policy2,
template<class> class policy3,
template<class> class policy4,
template<class> class policy5,
template<class> class policy6,
template<class> class policy7,
template<class> class policy8,
template<class> class policy9,
template<class> class policy10,
template<class> class policy11,
template<class> class policy12,
template<class> class policy13,
template<class> class policy14,
template<class> class policy15
#endif
> class nedallocator : public nedallocatorI::policycompositor<
#ifdef HAVE_CPP0XVARIADICTEMPLATES
nedallocatorI::baseimplementation<nedallocator<T, policies...> >,
policies...
#else
nedallocatorI::baseimplementation<nedallocator<T,
policy1, policy2, policy3, policy4, policy5,
policy6, policy7, policy8, policy9, policy10,
policy11, policy12, policy13, policy14, policy15
> >,
policy1, policy2, policy3, policy4, policy5,
policy6, policy7, policy8, policy9, policy10,
policy11, policy12, policy13, policy14, policy15
#endif
>::value
{
typedef typename nedallocatorI::policycompositor<
#ifdef HAVE_CPP0XVARIADICTEMPLATES
nedallocatorI::baseimplementation<nedallocator<T, policies...> >,
policies...
#else
nedallocatorI::baseimplementation<nedallocator<T,
policy1, policy2, policy3, policy4, policy5,
policy6, policy7, policy8, policy9, policy10,
policy11, policy12, policy13, policy14, policy15
> >,
policy1, policy2, policy3, policy4, policy5,
policy6, policy7, policy8, policy9, policy10,
policy11, policy12, policy13, policy14, policy15
#endif
>::value Base;
public:
nedallocator() { }
nedallocator(const nedallocator &o) : Base(o) { }
#ifdef HAVE_CPP0XRVALUEREFS
nedallocator(nedallocator &&o) : Base(std::move(o)) { }
#endif
/* This templated constructor and rebind() are used by MSVC's secure iterator checker.
I think it's best to not copy state even though it may break policies which store data. */
template<typename U> nedallocator(const nedallocator<U,
#ifdef HAVE_CPP0XVARIADICTEMPLATES
policies...
#else
policy1, policy2, policy3, policy4, policy5,
policy6, policy7, policy8, policy9, policy10,
policy11, policy12, policy13, policy14, policy15
#endif
> &o) { }
#ifdef HAVE_CPP0XRVALUEREFS
template<typename U> nedallocator(nedallocator<U,
#ifdef HAVE_CPP0XVARIADICTEMPLATES
policies...
#else
policy1, policy2, policy3, policy4, policy5,
policy6, policy7, policy8, policy9, policy10,
policy11, policy12, policy13, policy14, policy15
#endif
> &&o) { }
#endif
template<typename U> struct rebind {
typedef nedallocator<U,
#ifdef HAVE_CPP0XVARIADICTEMPLATES
policies...
#else
policy1, policy2, policy3, policy4, policy5,
policy6, policy7, policy8, policy9, policy10,
policy11, policy12, policy13, policy14, policy15
#endif
> other;
};
};
namespace nedallocatorI {
// Holds a static allocator instance shared by anything allocating from allocator
template<class allocator> struct StaticAllocator
{
static allocator &get()
{
static allocator a;
return a;
}
};
// RAII holder for a Newed object
template<typename T, class allocator> struct PtrHolder
{
T *mem;
PtrHolder(T *_mem) : mem(_mem) { }
~PtrHolder()
{
if(mem)
{
allocator &a=nedallocatorI::StaticAllocator<allocator>::get();
a.deallocate(mem, sizeof(T));
mem=0;
}
}
T *release() { T *ret=mem; mem=0; return ret; }
T *operator *() { return mem; }
const T *operator *() const { return mem; }
};
}
/*! \brief Allocates the memory for an instance of object \em T and constructs it.
If an exception is thrown during construction, the memory is freed before
rethrowing the exception.
Usage is very simple:
\code
SSEVectorType *foo1=New<SSEVectorType>(4, 5, 6, 7);
\endcode
*/
#ifdef HAVE_CPP0XVARIADICTEMPLATES
template<typename T, class allocator=nedallocator<T>, typename... Parameters> inline T *New(const Parameters&... parameters)
#else
template<typename T, class allocator> inline T *New()
#endif
{
allocator &a=nedallocatorI::StaticAllocator<allocator>::get();
nedallocatorI::PtrHolder<T, allocator> ret(a.allocate(sizeof(T)));
if(*ret)
{
#ifdef HAVE_CPP0XVARIADICTEMPLATES
new((void *) *ret) T(parameters...);
#else
new((void *) *ret) T;
#endif
}
return ret.release();
}
#ifndef HAVE_CPP0XVARIADICTEMPLATES
// Extremely annoying not to have default template arguments for functions pre-C++0x
template<typename T> inline T *New()
{
return New<T, nedallocator<T> >();
}
// Also, it's painful to replicate function overloads :(
#define NEDMALLOC_NEWIMPL \
template<typename T, class allocator, NEDMALLOC_NEWIMPLTYPES> inline T *New(NEDMALLOC_NEWIMPLPARSDEFS) \
{ \
allocator &a=nedallocatorI::StaticAllocator<allocator>::get(); \
nedallocatorI::PtrHolder<T, allocator> ret(a.allocate(sizeof(T))); \
if(*ret) \
{ \
new((void *) *ret) T(NEDMALLOC_NEWIMPLPARS); \
} \
return ret.release(); \
} \
template<typename T, NEDMALLOC_NEWIMPLTYPES> inline T *New(NEDMALLOC_NEWIMPLPARSDEFS)\
{ \
return New<T, nedallocator<T> >(NEDMALLOC_NEWIMPLPARS); \
}
#define NEDMALLOC_NEWIMPLTYPES typename P1
#define NEDMALLOC_NEWIMPLPARSDEFS const P1 &p1
#define NEDMALLOC_NEWIMPLPARS p1
NEDMALLOC_NEWIMPL
#undef NEDMALLOC_NEWIMPLTYPES
#undef NEDMALLOC_NEWIMPLPARSDEFS
#undef NEDMALLOC_NEWIMPLPARS
#define NEDMALLOC_NEWIMPLTYPES typename P1, typename P2
#define NEDMALLOC_NEWIMPLPARSDEFS const P1 &p1, const P2 &p2
#define NEDMALLOC_NEWIMPLPARS p1, p2
NEDMALLOC_NEWIMPL
#undef NEDMALLOC_NEWIMPLTYPES
#undef NEDMALLOC_NEWIMPLPARSDEFS
#undef NEDMALLOC_NEWIMPLPARS
#define NEDMALLOC_NEWIMPLTYPES typename P1, typename P2, typename P3
#define NEDMALLOC_NEWIMPLPARSDEFS const P1 &p1, const P2 &p2, const P3 &p3
#define NEDMALLOC_NEWIMPLPARS p1, p2, p3
NEDMALLOC_NEWIMPL
#undef NEDMALLOC_NEWIMPLTYPES
#undef NEDMALLOC_NEWIMPLPARSDEFS
#undef NEDMALLOC_NEWIMPLPARS
#define NEDMALLOC_NEWIMPLTYPES typename P1, typename P2, typename P3, typename P4
#define NEDMALLOC_NEWIMPLPARSDEFS const P1 &p1, const P2 &p2, const P3 &p3, const P4 &p4
#define NEDMALLOC_NEWIMPLPARS p1, p2, p3, p4
NEDMALLOC_NEWIMPL
#undef NEDMALLOC_NEWIMPLTYPES
#undef NEDMALLOC_NEWIMPLPARSDEFS
#undef NEDMALLOC_NEWIMPLPARS
#define NEDMALLOC_NEWIMPLTYPES typename P1, typename P2, typename P3, typename P4, typename P5
#define NEDMALLOC_NEWIMPLPARSDEFS const P1 &p1, const P2 &p2, const P3 &p3, const P4 &p4, const P5 &p5
#define NEDMALLOC_NEWIMPLPARS p1, p2, p3, p4, p5
NEDMALLOC_NEWIMPL
#undef NEDMALLOC_NEWIMPLTYPES
#undef NEDMALLOC_NEWIMPLPARSDEFS
#undef NEDMALLOC_NEWIMPLPARS
#undef NEDMALLOC_NEWIMPL
#endif
/*! \brief Destructs an instance of object T, and releases the memory used to store it.
*/
template<class allocator, typename T> inline void Delete(const T *_obj)
{
T *obj=const_cast<T *>(_obj);
allocator &a=nedallocatorI::StaticAllocator<allocator>::get();
obj->~T();
a.deallocate(obj, sizeof(T));
}
template<typename T> inline void Delete(const T *obj) { Delete<nedallocator<T> >(obj); }
/*! \class nedallocatorise
\ingroup C++
\brief Reimplements a given STL container to make full and efficient usage of nedalloc
\param stlcontainer The STL container you wish to reimplement
\param T The type to be contained
\param policies... Any policies you want applied to the allocator
This is a clever bit of C++ metaprogramming if I do say so myself! What it does
is to specialise a STL container implementation to make full use of nedalloc's
advanced facilities, so for example if you do:
\code
using namespace nedalloc;
typedef nedallocatorise<std::vector, unsigned int,
nedpolicy::typeIsPOD<true>::policy,
nedpolicy::mmap<>::policy,
nedpolicy::reserveN<26>::policy // 1<<26 = 64Mb. 10,000,000 * sizeof(unsigned int) = 38Mb.
>::value myvectortype;
myvectortype a;
for(int n=0; n<10000000; n++)
a.push_back(n);
\endcode
What happens here is that nedallocatorise reimplements the parts of
std::vector which extend and shrink the actual memory allocation.
Because the typeIsPOD policy is specified, it means that realloc()
rather than realloc(M2_PREVENT_MOVE) can be used. Also, because the
mmap and the reserveN policies are specified, std::vector immediately
reserves 64Mb of address space and forces the immediate use of mmap().
This allows you to push_back() a lot of data very, very quickly indeed.
You will also find that pop_back() actually reduces the allocation now
(most implementations don't bother ever releasing memory except when
reaching empty or when resize() is called). When mmapped, reserve()
is automatically held at a minimum of &lt;page size&gt;/sizeof(type) though
larger values are respected.
test.cpp has a benchmark of the speed differences you may realise, plus
an example of usage.
*/
template<template<typename, class> class stlcontainer,
typename T,
#ifdef HAVE_CPP0XVARIADICTEMPLATES
template<class> class... policies
#else
template<class> class policy1=nedpolicy::empty,
template<class> class policy2=nedpolicy::empty,
template<class> class policy3=nedpolicy::empty,
template<class> class policy4=nedpolicy::empty,
template<class> class policy5=nedpolicy::empty,
template<class> class policy6=nedpolicy::empty,
template<class> class policy7=nedpolicy::empty,
template<class> class policy8=nedpolicy::empty,
template<class> class policy9=nedpolicy::empty,
template<class> class policy10=nedpolicy::empty,
template<class> class policy11=nedpolicy::empty,
template<class> class policy12=nedpolicy::empty,
template<class> class policy13=nedpolicy::empty,
template<class> class policy14=nedpolicy::empty,
template<class> class policy15=nedpolicy::empty
#endif
> class nedallocatorise
{
public:
//! The reimplemented STL container type
typedef stlcontainer<T, nedallocator<T,
#ifdef HAVE_CPP0XVARIADICTEMPLATES
policies...
#else
policy1, policy2, policy3, policy4, policy5,
policy6, policy7, policy8, policy9, policy10,
policy11, policy12, policy13, policy14, policy15
#endif
> > value;
};
} /* namespace */
#endif
/* Some miscellaneous dlmalloc option documentation */
#ifdef DOXYGEN_IS_PARSING_ME
/* Just some false defines to keep doxygen happy */
#define NEDMALLOC_DEBUG DEBUG
#define ENABLE_LARGE_PAGES undef
#define ENABLE_FAST_HEAP_DETECTION undef
#define REPLACE_SYSTEM_ALLOCATOR undef
#define ENABLE_TOLERANT_NEDMALLOC undef
#define NO_NED_NAMESPACE undef
/*! \def MALLOC_ALIGNMENT
\brief Defines what alignment normally returned blocks should use. Is 16 bytes on Mac OS X, otherwise 8 bytes. */
#define MALLOC_ALIGNMENT 8
/*! \def USE_LOCKS
\brief Defines the threadsafety of nedalloc
USE_LOCKS can be 2 if you want to define your own MLOCK_T, INITIAL_LOCK,
ACQUIRE_LOCK, RELEASE_LOCK, TRY_LOCK, IS_LOCKED and NULL_LOCK_INITIALIZER.
*/
#define USE_LOCKS 1
/*! \def DEFAULT_GRANULARITY
\brief Defines the granularity in which to request or free system memory.
*/
#define DEFAULT_GRANULARITY (2*1024*1024)
/*! \def DEFAULT_TRIM_THRESHOLD
\brief Defines how much memory must be free before returning it to the system.
*/
#define DEFAULT_TRIM_THRESHOLD (2*1024*1024)
/*! \def DEFAULT_MMAP_THRESHOLD
\brief Defines the threshold above which mmap() is used to perform direct allocation.
*/
#define DEFAULT_MMAP_THRESHOLD (256*1024)
/*! \def MAX_RELEASE_CHECK_RATE
\brief Defines how many free() ops should occur before checking how much free memory there is.
*/
#define MAX_RELEASE_CHECK_RATE 4095
/*! \def NEDMALLOC_FORCERESERVE
\brief Lets you force address space reservation in the \b standard malloc API
Note that by default realloc() sets M2_RESERVE_MULT(8) when thunking to realloc2(),
so you probably don't need to override this
*/
#define NEDMALLOC_FORCERESERVE(p, mem, size) 0
/*! \def NEDMALLOC_TESTLOGENTRY
\brief Used to determine whether a given memory operation should be logged.
*/
#define NEDMALLOC_TESTLOGENTRY(tc, np, type, mspace, size, mem, alignment, flags, returned) ((type)&ENABLE_LOGGING)
/*! \def NEDMALLOC_STACKBACKTRACEDEPTH
\brief Turns on stack backtracing in the logger.
You almost certainly want to constrain what gets logged using NEDMALLOC_TESTLOGENTRY
if you turn this on as the sheer volume of data output can make execution very slow.
*/
#define NEDMALLOC_STACKBACKTRACEDEPTH 0
#endif
#endif
Loading...
举报
举报成功
我们将于2个工作日内通过站内信反馈结果给你!
请认真填写举报原因,尽可能描述详细。
请选择举报类型
取消
发送
误判申诉

此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。

如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。

取消
提交

简介

CPPS是一种轻量级的嵌入式脚本语言,其语法类似于C++。它具有当前主流语言的许多特性,包括协程、面向对象、lambda、闭包、泛型变量、自定义模块支持、GC垃圾收集和跨平台。CPPS将程序解释为字节码,通过内置语法解析在虚拟机中运行
取消

发行版 (3)

全部

开源评估指数源自 OSS-Compass 评估体系,评估体系围绕以下三个维度对项目展开评估:

1. 开源生态

  • 生产力:来评估开源项目输出软件制品和开源价值的能力。
  • 创新力:用于评估开源软件及其生态系统的多样化程度。
  • 稳健性:用于评估开源项目面对多变的发展环境,抵御内外干扰并自我恢复的能力。

2. 协作、人、软件

  • 协作:代表了开源开发行为中协作的程度和深度。
  • 人:观察开源项目核心人员在开源项目中的影响力,并通过第三方视角考察用户和开发者对开源项目的评价。
  • 软件:从开源项目对外输出的制品评估其价值最终落脚点。也是开源评估最"古老"的主流方向之一"开源软件" 的具体表现。

3. 评估模型

    基于"开源生态"与"协作、人、软件"的维度,找到与该目标直接或间接相关的可量化指标,对开源项目健康与生态进行量化评估,最终形成开源评估指数。

贡献者

全部

近期动态

不能加载更多了
编辑仓库简介
简介内容
主页
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化
C++
1
https://gitee.com/cppscript/cpps.git
git@gitee.com:cppscript/cpps.git
cppscript
cpps
cpps
master
点此查找更多帮助

搜索帮助

评论
仓库举报
回到顶部
登录提示
该操作需登录 Gitee 帐号,请先登录后再操作。
立即登录
没有帐号,去注册

AltStyle によって変換されたページ (->オリジナル) /