pax_global_header00006660000000000000000000000064122012020030014470gustar00rootroot0000000000000052 comment=722a30ce258eb38bee0a834406aed60a06f32d1d memtailor-master/000077500000000000000000000000001220120200300143165ustar00rootroot00000000000000memtailor-master/.gitignore000077500000000000000000000006601220120200300163130ustar00rootroot00000000000000# Compiled Object files *.slo *.lo *.o # Compiled Dynamic libraries *.so # Compiled Static libraries *.lai *.la *.a # Emacs backup files \#*\# *~ # Autotools generated files config.log config.status libtool .deps/ .dirstamp aclocal.m4 autom4te.cache/ Makefile.in Makefile configure .libs/ # Visual studio generated files *.suo *.sdf *.opensdf *.vcxproj.user output/ # Configure build targets deb/ debnoass/ pro/ rel/ relass/ memtailor-master/Makefile.am000077500000000000000000000034511220120200300163600ustar00rootroot00000000000000# options passed to aclocal, which is a tool for making macroes visible to # autoconf. We use -I to tell aclocal where we put the local macros. ACLOCAL_AMFLAGS = -I build/autotools/m4 # Options passed to the C PreProcessor (CPP), NOT the C Plus Plus compiler. AM_CPPFLAGS = -I${top_srcdir}/ # tell Libtool what the name of the library is. lib_LTLIBRARIES = libmemtailor.la # set the C++ compiler to include src/ AM_CXXFLAGS=-I$(top_srcdir)/src/ -std=gnu++0x # the sources that are built to make the library libmemtailor_la_SOURCES = \ src/memtailor/BufferPool.cpp src/memtailor/Arena.cpp \ src/memtailor/MemoryBlocks.cpp src/memtailor.cpp # The headers that are installed. memtailorA_includedir = $(includedir) memtailorA_include_HEADERS = src/memtailor.h # install remaining headers into a memtailor subdirectory of the include dir memtailorB_includedir = \ $(includedir)/memtailor memtailorB_include_HEADERS = src/memtailor/stdinc.h \ src/memtailor/BufferPool.h src/memtailor/Arena.h \ src/memtailor/ArenaVector.h src/memtailor/MemoryBlocks.h pkgconfigdir = $(libdir)/pkgconfig pkgconfig_DATA = build/autotools/memtailor.pc # When making a distribution file, Automake knows to include all files # that are necessary to build the project. EXTRA_DIST specifies files # to include beyond those used in the build process. EXTRA_DIST = autogen.sh # set up tests to run on "make check" if with_gtest TESTS=unittest check_PROGRAMS=$(TESTS) unittest_CXXFLAGS = -I$(top_srcdir)/src/ -std=gnu++0x unittest_LDFLAGS = $(top_builddir)/libmemtailor.la # test_LIBS= unittest_SOURCES=src/test/ArenaTest.cpp src/test/BufferPoolTest.cpp \ src/test/MemoryBlocksTest.cpp src/test/testMain.cpp \ src/test/gtestInclude.cpp else check: @echo @echo "Configure did not locate gtest, so unittests cannot be run." endif memtailor-master/README.md000077500000000000000000000017231220120200300156030ustar00rootroot00000000000000memtailor ========= Memtailor is a C++ library of special purpose memory allocators. It currently offers an arena allocator and a memory pool. The main motivation to use a memtailor allocator is better and more predictable performance than you get with new/delete. Sometimes a memtailor allocator can also be more convenient due to the ability to free many allocations at one time. The Memtailor memory pool is useful if you need to do many allocations of a fixed size. For example a memory pool is well suited to allocate the nodes in a linked list. You can think of the Memtailor arena allocator as being similar to stack allocation. Both kinds of allocation are very fast and require you to allocate/deallocate memory in last-in-first-out order. Arena allocation has the further benefits that it stays within the C++ standard, it will not cause a stack overflow, you can have multiple arena allocators at the same time and allocation is not tied to a function invocation. memtailor-master/autogen.sh000077500000000000000000000001221220120200300163120ustar00rootroot00000000000000#!/bin/sh srcdir="`dirname '$0'`" autoreconf --verbose --install --force $srcdir memtailor-master/build/000077500000000000000000000000001220120200300154155ustar00rootroot00000000000000memtailor-master/build/archlinux/000077500000000000000000000000001220120200300174125ustar00rootroot00000000000000memtailor-master/build/archlinux/PKGBUILD000066400000000000000000000015141220120200300205370ustar00rootroot00000000000000# Maintainer: Oleksandr Motsak pkgname=memtailor pkgver=20120608 pkgrel=1 pkgdesc="Custom memory manager. Has an arena allocator and a memory pool." arch=(i686 x86_64) url="http://www.broune.com/" license=('license.txt') makedepends=('automake' 'autoconf' 'mercurial') checkdepends=('gtest') _hgname="$pkgname" _hgroot="https://bitbucket.org/malex984/$pkgname" build() { cd "$srcdir" msg "Connecting to mercurial server…" if [ -d "$srcdir/$_hgname" ] then cd $_hgname && hg pull && cd .. else hg clone $_hgroot fi # setup "./$_hgname/autogen.sh" mkdir -p "BUILD" msg "Starting (out-of-source-tree) build..." cd "BUILD" && ../$_hgname/configure --prefix=/usr && make && cd .. } package() { cd "$srcdir/BUILD" make DESTDIR="${pkgdir}" install } check() { cd "$srcdir/BUILD" make check } memtailor-master/build/autotools/000077500000000000000000000000001220120200300174465ustar00rootroot00000000000000memtailor-master/build/autotools/.gitignore000077500000000000000000000001701220120200300214370ustar00rootroot00000000000000# Autotools generated files ar-lib config.guess config.sub depcomp install-sh ltmain.sh memtailor-*.pc missing memtailor-master/build/autotools/m4/000077500000000000000000000000001220120200300177665ustar00rootroot00000000000000memtailor-master/build/autotools/m4/.gitignore000077500000000000000000000001411220120200300217550ustar00rootroot00000000000000# Autotools generated files libtool.m4 ltoptions.m4 ltsugar.m4 ltversion.m4 lt~obsolete.m4 memtailor-master/build/autotools/m4/empty000066400000000000000000000000001220120200300210350ustar00rootroot00000000000000memtailor-master/build/autotools/memtailor.pc.in000077500000000000000000000004461220120200300223770ustar00rootroot00000000000000prefix=@prefix@ exec_prefix=@exec_prefix@ libdir=@libdir@ includedir=@includedir@ Name: memtailor Description: C++ library of special purpose memory allocators. URL: https://github.com/broune/memtailor Requires: Version: @PACKAGE_VERSION@ Libs: -L${libdir} -lmemtailor Cflags: -I${includedir} memtailor-master/build/vs12/000077500000000000000000000000001220120200300162105ustar00rootroot00000000000000memtailor-master/build/vs12/memtailor-lib/000077500000000000000000000000001220120200300207455ustar00rootroot00000000000000memtailor-master/build/vs12/memtailor-lib/memtailor-lib.vcxproj000077500000000000000000000472051220120200300251320ustar00rootroot00000000000000 Debug-NoAssert Win32 Debug-NoAssert x64 Debug Win32 Debug x64 Release-Assert Win32 Release-Assert x64 Release Win32 Release x64 WarningAsError Win32 WarningAsError x64 {534C44F8-BA0A-4AF0-95F1-260CA8EF3551} Win32Proj memtailorlib StaticLibrary true v110 Unicode StaticLibrary true v110 Unicode StaticLibrary true v110 Unicode StaticLibrary true v110 Unicode StaticLibrary true v110 Unicode StaticLibrary true v110 Unicode StaticLibrary false v110 true Unicode StaticLibrary false v110 true Unicode StaticLibrary false v110 false Unicode StaticLibrary false v110 false Unicode $(SolutionDir)\output\$(Platform)\$(Configuration)\ $(SolutionDir)\output\$(Platform)\$(Configuration)\intermediate\$(MSBuildProjectName)\ memtailor $(SolutionDir)\output\$(Platform)\$(Configuration)\ $(SolutionDir)\output\$(Platform)\$(Configuration)\intermediate\$(MSBuildProjectName)\ memtailor $(SolutionDir)\output\$(Platform)\$(Configuration)\ $(SolutionDir)\output\$(Platform)\$(Configuration)\intermediate\$(MSBuildProjectName)\ memtailor $(SolutionDir)\output\$(Platform)\$(Configuration)\ $(SolutionDir)\output\$(Platform)\$(Configuration)\intermediate\$(MSBuildProjectName)\ memtailor $(SolutionDir)\output\$(Platform)\$(Configuration)\ $(SolutionDir)\output\$(Platform)\$(Configuration)\intermediate\$(MSBuildProjectName)\ memtailor $(SolutionDir)\output\$(Platform)\$(Configuration)\ $(SolutionDir)\output\$(Platform)\$(Configuration)\intermediate\$(MSBuildProjectName)\ memtailor $(SolutionDir)\output\$(Platform)\$(Configuration)\ $(SolutionDir)\output\$(Platform)\$(Configuration)\intermediate\$(MSBuildProjectName)\ memtailor $(SolutionDir)\output\$(Platform)\$(Configuration)\ $(SolutionDir)\output\$(Platform)\$(Configuration)\intermediate\$(MSBuildProjectName)\ memtailor $(SolutionDir)\output\$(Platform)\$(Configuration)\ $(SolutionDir)\output\$(Platform)\$(Configuration)\intermediate\$(MSBuildProjectName)\ memtailor $(SolutionDir)\output\$(Platform)\$(Configuration)\ $(SolutionDir)\output\$(Platform)\$(Configuration)\intermediate\$(MSBuildProjectName)\ memtailor Level3 Disabled MEMTAILOR_DEBUG;WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions) true false Windows true Level3 Disabled MEMTAILOR_DEBUG;WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions) true false true Windows true Level3 Disabled MEMTAILOR_DEBUG;WIN64;_DEBUG;_LIB;%(PreprocessorDefinitions) true false Windows true Level3 Disabled MEMTAILOR_DEBUG;WIN64;_DEBUG;_LIB;%(PreprocessorDefinitions) true false Windows true Level3 Disabled WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions) true false Windows true Level3 Disabled WIN64;NDEBUG;_LIB;%(PreprocessorDefinitions) true false Windows true Level3 MaxSpeed true true WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions) true Windows true true true Level3 MaxSpeed true true WIN64;NDEBUG;_LIB;%(PreprocessorDefinitions) true true Windows true true true Level3 MaxSpeed true true MEMTAILOR_DEBUG;WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions) true MultiThreadedDebugDLL Windows true true true Level3 MaxSpeed true true MEMTAILOR_DEBUG;WIN64;_DEBUG;_LIB;%(PreprocessorDefinitions) true MultiThreadedDebugDLL Windows true true true memtailor-master/build/vs12/memtailor-lib/memtailor-lib.vcxproj.filters000077500000000000000000000034521220120200300265750ustar00rootroot00000000000000 {4FC737F1-C7A5-4376-A066-2A32D752A2FF} cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx {93995380-89BD-4b04-88EB-625FBE52EBFB} h;hpp;hxx;hm;inl;inc;xsd {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms Source Files Source Files Source Files Header Files Header Files Header Files Header Files Header Files memtailor-master/build/vs12/memtailor-test/000077500000000000000000000000001220120200300211565ustar00rootroot00000000000000memtailor-master/build/vs12/memtailor-test/memtailor-test.vcxproj000077500000000000000000000577701220120200300255640ustar00rootroot00000000000000 Debug-NoAssert Win32 Debug-NoAssert x64 Debug Win32 Debug x64 Release-Assert Win32 Release-Assert x64 Release Win32 Release x64 WarningAsError Win32 WarningAsError x64 {CEB92301-588A-4C62-8523-1A65D4AE15CB} Win32Proj memtailortest Application true v110 Unicode Application true v110 Unicode Application true v110 Unicode Application true v110 Unicode Application true v110 Unicode Application true v110 Unicode Application false v110 true Unicode Application false v110 true Unicode Application false v110 false Unicode Application false v110 false Unicode true $(SolutionDir)\output\$(Platform)\$(Configuration)\ $(SolutionDir)\intermediate\$(Platform)\$(Configuration)\ true $(SolutionDir)\output\$(Platform)\$(Configuration)\ $(SolutionDir)\intermediate\$(Platform)\$(Configuration)\ true $(SolutionDir)\output\$(Platform)\$(Configuration)\ $(SolutionDir)\intermediate\$(Platform)\$(Configuration)\ true $(SolutionDir)\output\$(Platform)\$(Configuration)\ $(SolutionDir)\intermediate\$(Platform)\$(Configuration)\ true $(SolutionDir)\output\$(Platform)\$(Configuration)\ $(SolutionDir)\intermediate\$(Platform)\$(Configuration)\ true $(SolutionDir)\output\$(Platform)\$(Configuration)\ $(SolutionDir)\intermediate\$(Platform)\$(Configuration)\ false $(SolutionDir)\output\$(Platform)\$(Configuration)\ $(SolutionDir)\intermediate\$(Platform)\$(Configuration)\ false $(SolutionDir)\output\$(Platform)\$(Configuration)\ $(SolutionDir)\intermediate\$(Platform)\$(Configuration)\ false $(SolutionDir)\output\$(Platform)\$(Configuration)\ $(SolutionDir)\intermediate\$(Platform)\$(Configuration)\ false $(SolutionDir)\output\$(Platform)\$(Configuration)\ $(SolutionDir)\intermediate\$(Platform)\$(Configuration)\ Level3 Disabled _VARIADIC_MAX=10;MEMTAILOR_DEBUG;WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) ..\..\..\..\gtest\;..\..\..\..\gtest\include\;..\..\..\src;%(AdditionalIncludeDirectories) true false Console true kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) Level3 Disabled _VARIADIC_MAX=10;MEMTAILOR_DEBUG;WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) ..\..\..\..\gtest\;..\..\..\..\gtest\include\;..\..\..\src;%(AdditionalIncludeDirectories) true false true Console true kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) Level3 Disabled _VARIADIC_MAX=10;MEMTAILOR_DEBUG;WIN64;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) ..\..\..\..\gtest\;..\..\..\..\gtest\include\;..\..\..\src;%(AdditionalIncludeDirectories) true false Console true kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) Level3 Disabled _VARIADIC_MAX=10;MEMTAILOR_DEBUG;WIN64;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) ..\..\..\..\gtest\;..\..\..\..\gtest\include\;..\..\..\src;%(AdditionalIncludeDirectories) true false Console true kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) Level3 Disabled _VARIADIC_MAX=10;WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) ..\..\..\..\gtest\;..\..\..\..\gtest\include\;..\..\..\src;%(AdditionalIncludeDirectories) true false Console true kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) Level3 Disabled _VARIADIC_MAX=10;WIN64;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) ..\..\..\..\gtest\;..\..\..\..\gtest\include\;..\..\..\src;%(AdditionalIncludeDirectories) true false Console true kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) Level3 MaxSpeed true true _VARIADIC_MAX=10;WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) ..\..\..\..\gtest\;..\..\..\..\gtest\include\;..\..\..\src;%(AdditionalIncludeDirectories) true Console true true true kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) Level3 MaxSpeed true true _VARIADIC_MAX=10;WIN64;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) ..\..\..\..\gtest\;..\..\..\..\gtest\include\;..\..\..\src;%(AdditionalIncludeDirectories) true Console true true true kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) Level3 MaxSpeed true true _VARIADIC_MAX=10;MEMTAILOR_DEBUG;WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) ..\..\..\..\gtest\;..\..\..\..\gtest\include\;..\..\..\src;%(AdditionalIncludeDirectories) true MultiThreadedDebugDLL Console true true true kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) Level3 MaxSpeed true true _VARIADIC_MAX=10;MEMTAILOR_DEBUG;WIN64;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) ..\..\..\..\gtest\;..\..\..\..\gtest\include\;..\..\..\src;%(AdditionalIncludeDirectories) true MultiThreadedDebugDLL Console true true true kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) {534c44f8-ba0a-4af0-95f1-260ca8ef3551} memtailor-master/build/vs12/memtailor-test/memtailor-test.vcxproj.filters000077500000000000000000000026461220120200300272230ustar00rootroot00000000000000 {4FC737F1-C7A5-4376-A066-2A32D752A2FF} cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx {93995380-89BD-4b04-88EB-625FBE52EBFB} h;hpp;hxx;hm;inl;inc;xsd {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms Source Files Source Files Source Files Source Files Source Files memtailor-master/build/vs12/memtailor.sln000077500000000000000000000111321220120200300207200ustar00rootroot00000000000000 Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio 2012 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "memtailor-lib", "memtailor-lib\memtailor-lib.vcxproj", "{534C44F8-BA0A-4AF0-95F1-260CA8EF3551}" EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "memtailor-test", "memtailor-test\memtailor-test.vcxproj", "{CEB92301-588A-4C62-8523-1A65D4AE15CB}" ProjectSection(ProjectDependencies) = postProject {534C44F8-BA0A-4AF0-95F1-260CA8EF3551} = {534C44F8-BA0A-4AF0-95F1-260CA8EF3551} EndProjectSection EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Win32 = Debug|Win32 Debug|x64 = Debug|x64 Debug-NoAssert|Win32 = Debug-NoAssert|Win32 Debug-NoAssert|x64 = Debug-NoAssert|x64 Release|Win32 = Release|Win32 Release|x64 = Release|x64 Release-Assert|Win32 = Release-Assert|Win32 Release-Assert|x64 = Release-Assert|x64 WarningAsError|Win32 = WarningAsError|Win32 WarningAsError|x64 = WarningAsError|x64 EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution {534C44F8-BA0A-4AF0-95F1-260CA8EF3551}.Debug|Win32.ActiveCfg = Debug|Win32 {534C44F8-BA0A-4AF0-95F1-260CA8EF3551}.Debug|Win32.Build.0 = Debug|Win32 {534C44F8-BA0A-4AF0-95F1-260CA8EF3551}.Debug|x64.ActiveCfg = Debug|x64 {534C44F8-BA0A-4AF0-95F1-260CA8EF3551}.Debug|x64.Build.0 = Debug|x64 {534C44F8-BA0A-4AF0-95F1-260CA8EF3551}.Debug-NoAssert|Win32.ActiveCfg = Debug-NoAssert|Win32 {534C44F8-BA0A-4AF0-95F1-260CA8EF3551}.Debug-NoAssert|Win32.Build.0 = Debug-NoAssert|Win32 {534C44F8-BA0A-4AF0-95F1-260CA8EF3551}.Debug-NoAssert|x64.ActiveCfg = Debug-NoAssert|x64 {534C44F8-BA0A-4AF0-95F1-260CA8EF3551}.Debug-NoAssert|x64.Build.0 = Debug-NoAssert|x64 {534C44F8-BA0A-4AF0-95F1-260CA8EF3551}.Release|Win32.ActiveCfg = Release|Win32 {534C44F8-BA0A-4AF0-95F1-260CA8EF3551}.Release|Win32.Build.0 = Release|Win32 {534C44F8-BA0A-4AF0-95F1-260CA8EF3551}.Release|x64.ActiveCfg = Release|x64 {534C44F8-BA0A-4AF0-95F1-260CA8EF3551}.Release|x64.Build.0 = Release|x64 {534C44F8-BA0A-4AF0-95F1-260CA8EF3551}.Release-Assert|Win32.ActiveCfg = Release-Assert|Win32 {534C44F8-BA0A-4AF0-95F1-260CA8EF3551}.Release-Assert|Win32.Build.0 = Release-Assert|Win32 {534C44F8-BA0A-4AF0-95F1-260CA8EF3551}.Release-Assert|x64.ActiveCfg = Release-Assert|x64 {534C44F8-BA0A-4AF0-95F1-260CA8EF3551}.Release-Assert|x64.Build.0 = Release-Assert|x64 {534C44F8-BA0A-4AF0-95F1-260CA8EF3551}.WarningAsError|Win32.ActiveCfg = WarningAsError|Win32 {534C44F8-BA0A-4AF0-95F1-260CA8EF3551}.WarningAsError|Win32.Build.0 = WarningAsError|Win32 {534C44F8-BA0A-4AF0-95F1-260CA8EF3551}.WarningAsError|x64.ActiveCfg = WarningAsError|x64 {534C44F8-BA0A-4AF0-95F1-260CA8EF3551}.WarningAsError|x64.Build.0 = WarningAsError|x64 {CEB92301-588A-4C62-8523-1A65D4AE15CB}.Debug|Win32.ActiveCfg = Debug|Win32 {CEB92301-588A-4C62-8523-1A65D4AE15CB}.Debug|Win32.Build.0 = Debug|Win32 {CEB92301-588A-4C62-8523-1A65D4AE15CB}.Debug|x64.ActiveCfg = Debug|x64 {CEB92301-588A-4C62-8523-1A65D4AE15CB}.Debug|x64.Build.0 = Debug|x64 {CEB92301-588A-4C62-8523-1A65D4AE15CB}.Debug-NoAssert|Win32.ActiveCfg = Debug-NoAssert|Win32 {CEB92301-588A-4C62-8523-1A65D4AE15CB}.Debug-NoAssert|Win32.Build.0 = Debug-NoAssert|Win32 {CEB92301-588A-4C62-8523-1A65D4AE15CB}.Debug-NoAssert|x64.ActiveCfg = Debug-NoAssert|x64 {CEB92301-588A-4C62-8523-1A65D4AE15CB}.Debug-NoAssert|x64.Build.0 = Debug-NoAssert|x64 {CEB92301-588A-4C62-8523-1A65D4AE15CB}.Release|Win32.ActiveCfg = Release|Win32 {CEB92301-588A-4C62-8523-1A65D4AE15CB}.Release|Win32.Build.0 = Release|Win32 {CEB92301-588A-4C62-8523-1A65D4AE15CB}.Release|x64.ActiveCfg = Release|x64 {CEB92301-588A-4C62-8523-1A65D4AE15CB}.Release|x64.Build.0 = Release|x64 {CEB92301-588A-4C62-8523-1A65D4AE15CB}.Release-Assert|Win32.ActiveCfg = Release-Assert|Win32 {CEB92301-588A-4C62-8523-1A65D4AE15CB}.Release-Assert|Win32.Build.0 = Release-Assert|Win32 {CEB92301-588A-4C62-8523-1A65D4AE15CB}.Release-Assert|x64.ActiveCfg = Release-Assert|x64 {CEB92301-588A-4C62-8523-1A65D4AE15CB}.Release-Assert|x64.Build.0 = Release-Assert|x64 {CEB92301-588A-4C62-8523-1A65D4AE15CB}.WarningAsError|Win32.ActiveCfg = WarningAsError|Win32 {CEB92301-588A-4C62-8523-1A65D4AE15CB}.WarningAsError|Win32.Build.0 = WarningAsError|Win32 {CEB92301-588A-4C62-8523-1A65D4AE15CB}.WarningAsError|x64.ActiveCfg = WarningAsError|x64 {CEB92301-588A-4C62-8523-1A65D4AE15CB}.WarningAsError|x64.Build.0 = WarningAsError|x64 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE EndGlobalSection EndGlobal memtailor-master/configure.ac000077500000000000000000000121251220120200300166100ustar00rootroot00000000000000dnl AC_INIT sets up autoconf and must be first macro. AC_INIT([memtailor], [1.0]) # package, version, bug-report-email # set up information about directories AC_CONFIG_MACRO_DIR([build/autotools/m4]) # directory of extra autoconf macroes AC_CONFIG_AUX_DIR([build/autotools]) # directory for auxiliary build tools (install-sh etc) # check that source directory is correct dnl if autoconf is told the source code is in a directory that does not dnl contain this file then it knows that the directory is wrong. AC_CONFIG_SRCDIR([src/memtailor.h]) dnl ----- The gtest dependency AC_ARG_WITH([gtest], AS_HELP_STRING( [--with-gtest], [use gtest, which is required for running the unit tests with make check. The value download, which is the default, downloads gtest if a gtest source directory cannot be found. Per the recommendation of the gtest documentation, gtest is compiled with the tests, so an installed gtest is not usable - you need the gtest source. GTEST_PATH indicates where to look for gtest and it is also where gtest will be downloaded to if not found. The default path is srcdir/libs so that gtest needs to be at srcdir/libs/gtest/ where srcdir is the base of the directory being configured from.] )) AC_MSG_CHECKING([for gtest]) AS_IF([test "x$GTEST_PATH" == "x"], [GTEST_PATH="$srcdir/libs"]) AS_IF([test "x$GTEST_VERSION" == "x"], [GTEST_VERSION="1.6.0"]) AS_IF([test "x$with_gtest" == "x"], [with_gtest="download"]) AS_IF([test "x$with_gtest" == "xdownload"], [with_gtest="yes"; AC_CHECK_FILE([$GTEST_PATH/gtest/src/gtest-all.cc], [], [ mkdir -p "$GTEST_PATH"; ( cd $GTEST_PATH; rm -rf gtest-$GTEST_VERSION.zip wget http://googletest.googlecode.com/files/gtest-$GTEST_VERSION.zip; unzip gtest-$GTEST_VERSION.zip; rm gtest-$GTEST_VERSION.zip rm -rf gtest/ mv gtest-$GTEST_VERSION/ gtest/ ); if test ! -e "$GTEST_PATH/gtest/src/gtest-all.cc"; then AC_MSG_WARN([Failed to download or extract gtest.]); with_gtest="no"; else with_gtest="yes"; fi ])], [test "x$with_gtest" == "xyes"], [ AC_CHECK_FILE([$GTEST_PATH/gtest/src/gtest-all.cc], [], [ AC_MSG_ERROR([could not find gtest source at path $GTEST_PATH.]) ]) ], [test "x$with_gtest" == "xno"], [], [AC_MSG_ERROR([invalid value $with_gtest for with_gtest.])] ) AS_IF([test "x$with_gtest" == "xyes"], [GTEST_CFLAGS="-I`cd $GTEST_PATH/gtest/include; echo $PWD` -I`cd $GTEST_PATH/gtest/; echo $PWD`"]); AM_CONDITIONAL(with_gtest, test "x$with_gtest" == "xyes") DEPS_CFLAGS="$GTEST_CFLAGS" DEPS_LIBS="$GTEST_LIBS" AC_SUBST(DEPS_CFLAGS) AC_SUBST(DEPS_LIBS) # Enable optional maintainer mode (off by default) dnl AM_MAINTAINER_MODE turns off automatic reconstruction of the build dnl files if the source build files have changed. A developer will want dnl those automatic reconstructions to happen so that changes to the dnl build system are actually carried out. However, a user might not dnl have the tools required to reconfigure and the need for dnl reconstruction might be spurious if the last-modified date is set dnl incorrectly on the build files. dnl dnl Passing the option [enable] to AM_MAINTAINER_MODE makes the dnl non-reconstruction feature available, but only when turned on by dnl passing the option –disable-maintainer-mode. This option is dnl apparently useful to some package distributors. AM_MAINTAINER_MODE([enable]) # Set up Automake dnl foreign: do not create the GNU-specific file COPYING and do not complain dnl that GNU-specific files like NEWS, README, AUTHORS and ChangeLog are dnl missing. dnl -Wall: set Automake to emit all warnings it can. Is NOT RELATED to setting dnl warnings for other tools. For example, it wil not make the compiler dnl get a -Wall option. dnl subdir-objects: Put object files in a directory structure based on dnl the directory structure of the source files. This way, two source dnl files with the same name in different directories do not conflict. AM_INIT_AUTOMAKE([foreign subdir-objects -Wall]) # if --enable-silent-rules is passed to ./configure or if V=0 is passed # to make, then the compilation output will be much less verbose making # it possible to spot warnings and errors as they go by. AM_SILENT_RULES() # Set up the $(LN_S) macro, which creates symbolic links AC_PROG_LN_S # set output variable INSTALL to the name of a BSD-compatible install program. # Requires install-sh to be present as a fallback, even on systems where # the fallback is not used. AC_PROG_INSTALL # Locate the C++ compiler. AC_PROG_CXX # Set up LibTool LT_INIT dnl Set the version for the library -- this concerns compatibility of the dnl source and binary interface of the library and is not the same as the dnl version of the project. AC_SUBST([MEMTAILOR_SO_VERSION], [0:0:0]) dnl Set up AC_OUTPUT to create each file by copying an input file dnl while substituting the output variable values. AC_CONFIG_FILES([Makefile build/autotools/memtailor.pc:build/autotools/memtailor.pc.in]) dnl Macro that is required to be at the end of any Autoconf script. dnl Creates config.status and launches it. AC_OUTPUT memtailor-master/fixspace000077500000000000000000000042771220120200300160600ustar00rootroot00000000000000#!/bin/bash # Does the following operations on the files passed as arguments: # - Remove trailing space from lines # - Remove trailing blank lines # - Remove/convert DOS-style line breaks # - Expand tabs to spaces with a tabspace of 4 # I once had an error where the conversion had an error (the computer # didn't have dos2unix), resulting in the converted files being empty. # The result was that every file got replaced by an empty file! That # was not so nice, so this script stops operation as soon as any error # occurs, and it also checks that only space has been changed before # it overwrites the original file with a space-fixed version. for f in $*; do echo $f; tr -d '\r' < $f > __spaceTmp0; if [ $? != 0 ]; then echo "There was an error removing DOS-style line breaks."; exit 1; fi; expand -4 < __spaceTmp0 > __spaceTmp1; if [ $? != 0 ]; then echo "There was an error expanding tabs."; exit 1; fi; sed 's/[[:blank:]]*$//g' < __spaceTmp1 > __spaceTmp2; if [ $? != 0 ]; then echo "There was an error eliminating trailing space from lines."; exit 1; fi; # Make completely sure that we only changed the spaces diff -EbwB -q $f __spaceTmp2; if [ $? != 0 ]; then echo "There was an error. Conversion not confirmed correct."; exit 1; fi; sed -e :a -e '/^\n*$/{$d;N;ba' -e '}' < __spaceTmp2 > __spaceTmp3; if [ $? != 0 ]; then echo "There was an error eliminating trailing blank lines."; exit 1; fi; # We have to do diff twice, because diff will not ignore trailing # lines that consist only of spaces. It will ignore changes to space and removal of # completely empty lines, so if we do it twice we get the right thing. # Make completely sure that we only changed the spaces diff -EbwB -q __spaceTmp2 __spaceTmp3; if [ $? != 0 ]; then echo "There was an error. Conversion not confirmed correct."; exit 1; fi; diff -q $f __spaceTmp3 1>/dev/null; if [ $? != 0 ]; then mv -f __spaceTmp3 $f; if [ $? != 0 ]; then echo "There was an error moving fixed file into place."; exit 1; fi; echo "Fixed space issue for $f." fi rm -f __spaceTmp0 __spaceTmp1 __spaceTmp2 __spaceTmp3; if [ $? != 0 ]; then echo "There was an error removing temporary files."; exit 1; fi; done; memtailor-master/libs/000077500000000000000000000000001220120200300152475ustar00rootroot00000000000000memtailor-master/libs/.gitignore000077500000000000000000000000071220120200300172370ustar00rootroot00000000000000gtest/ memtailor-master/license.txt000077500000000000000000000030061220120200300165030ustar00rootroot00000000000000Copyright (c) 2011, Bjarke Hammersholt Roune All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * 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. * Neither the name of the University of Cornell nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 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. memtailor-master/replace000077500000000000000000000003321220120200300156550ustar00rootroot00000000000000#!/bin/bash echo "Running script \"sed s/$1/$2/\"" for i in 1 2 3; do /usr/bin/sleep 1; echo -n .; done for f in `ls src/*.cpp src/*.h`; do echo "Processing $f"; sed "s/$1/$2/" < $f > $f.tmp mv $f.tmp $f done memtailor-master/src/000077500000000000000000000000001220120200300151055ustar00rootroot00000000000000memtailor-master/src/memtailor.cpp000077500000000000000000000003461220120200300176100ustar00rootroot00000000000000/* Copyright (C) 2013 Bjarke Hammersholt Roune (www.broune.com) MemTailor is distributed under the Modified BSD License. See license.txt. */ #include "memtailor.h" extern "C" { void libmemtailorIsPresent(void) {} } memtailor-master/src/memtailor.h000077500000000000000000000011651220120200300172550ustar00rootroot00000000000000/* Copyright (C) 2011 Bjarke Hammersholt Roune (www.broune.com) MemTailor is distributed under the Modified BSD License. See license.txt. */ #ifndef MEMT_ALL_GUARD #define MEMT_ALL_GUARD // Include this file to pull in all external MemTailor files #include "memtailor/Arena.h" #include "memtailor/ArenaVector.h" #include "memtailor/BufferPool.h" extern "C" { // Put a C function in the library so that it can be detected by the autoconf // macro AC_CHECK_LIB. That macro can only check for libraries that contain // at least one C function. void libmemtailorIsPresent(void); // This function does nothing. } #endif memtailor-master/src/memtailor/000077500000000000000000000000001220120200300170765ustar00rootroot00000000000000memtailor-master/src/memtailor/Arena.cpp000077500000000000000000000044331220120200300206370ustar00rootroot00000000000000/* Copyright (C) 2011 Bjarke Hammersholt Roune (www.broune.com) MemTailor is distributed under the Modified BSD License. See license.txt. */ #include "Arena.h" #include namespace memt { Arena Arena::_scratchArena; Arena::Arena() { } Arena::~Arena() { freeAllAllocsAndBackingMemory(); } void Arena::freeAllAllocs() { while (block().hasPreviousBlock()) _blocks.freePreviousBlock(); block().clear(); } void Arena::freeAllAllocsAndBackingMemory() { _blocks.freeAllBlocks(); #ifdef MEMT_DEBUG std::vector().swap(_debugAllocs); #endif } bool Arena::fromArena(void const* ptr) { Block const* block = _blocks.blockOf(ptr); if (block == 0) return false; // check < instead of <= as we do not count pointers that are // one-past-the-end. return ptr < block->position(); } void Arena::growCapacity(const size_t needed) { // ** Calcuate size of block (doubles capacity) size_t size = std::max(needed, block().getBytesInBlock()); if (size > std::numeric_limits::max() / 2) throw std::bad_alloc(); // size * 2 overflows size *= 2; const size_t minimumAlloc = 16 * 1024 - sizeof(Block) - 16; size = std::max(size, minimumAlloc); // avoid many small blocks size = MemoryBlocks::alignThrowOnOverflow(size); MEMT_ASSERT(size >= needed); MEMT_ASSERT(size % MemoryAlignment == 0); _blocks.allocBlock(size); } void Arena::freeTopFromOldBlock(void* ptr) { MEMT_ASSERT(ptr != 0); MEMT_ASSERT(block().empty()); MEMT_ASSERT(block().hasPreviousBlock()); Block* previous = block().previousBlock(); MEMT_ASSERT(previous->isInBlock(ptr)); previous->setPosition(ptr); if (previous->empty()) _blocks.freePreviousBlock(); } void Arena::freeAndAllAfterFromOldBlock(void* ptr) { MEMT_ASSERT(!block().isInBlock(ptr)); MEMT_ASSERT(block().previousBlock() != 0); block().setPosition(block().begin()); while (!(block().previousBlock()->isInBlock(ptr))) { _blocks.freePreviousBlock(); MEMT_ASSERT(block().hasPreviousBlock()); // ptr must be in some block } MEMT_ASSERT(block().previousBlock()->isInBlock(ptr)); block().previousBlock()->setPosition(ptr); if (block().previousBlock()->empty()) _blocks.freePreviousBlock(); } } memtailor-master/src/memtailor/Arena.h000077500000000000000000000367051220120200300203130ustar00rootroot00000000000000/* Copyright (C) 2011 Bjarke Hammersholt Roune (www.broune.com) MemTailor is distributed under the Modified BSD License. See license.txt. */ #ifndef MEMT_ARENA_GUARD #define MEMT_ARENA_GUARD #include "MemoryBlocks.h" #include "stdinc.h" #include #include #include #include #ifdef MEMT_DEBUG #include #endif namespace memt { /** This is an arena allocator. Arena allocators are very fast at the cost of imposing limitations on how memory can be deallocated. Allocation and deallocation must occur in stack order (LIFO). In other words, only the most recently allocated buffer that has not been deallocated yet can be deallocated. It is also possible to deallocate all buffers that were deallocated after a given buffer. In DEBUG mode stack order is enforced by ASSERTs. Arena satisfies allocation requests out of a larger block of memory. When a block is exhausted another block must be allocated using new. This new block is at least twice the size of the previous block. Old blocks are never re-used though they will be deallocated if they become old. So the current block is replaced if and only if it becomes exhausted. The scheme of geometric block growth is used because it allows a very fast implementation with excellent locality of reference. This can consume memory beyond that which the user of the Arena needs - all allocators have memory overhead. Optimal performance on both speed and memory consumption can usully be reached by all code using the same Arena object when that is possible given the stack-order limitation on deallocation. All methods throw bad_alloc if backing memory allocation using new fails. */ class Arena { public: Arena(); ~Arena(); // ***** Basic void* interface ***** /** Returns a pointer to a buffer of size bytes. Throws bad_alloc if that is not possible. All allocated and not freed buffers have unique addresses even when size is zero. */ void* alloc(size_t size); /** Frees the buffer pointed to by ptr. That buffer must be the most recently allocated buffer from this Arena that has not yet been freed. Double frees are not allowed. ptr must not be null. */ void freeTop(void* ptr); /** Frees the buffer pointed to by ptr and all not yet freed allocations that have happened since that buffer was allocated. ptr must not be null. */ void freeAndAllAfter(void* ptr); /** Marks all previous allocations as freed. Does not deallocate all the backing memory. */ void freeAllAllocs(); /** Marks all previous allocations as freed and deallocates all backing memory. */ void freeAllAllocsAndBackingMemory(); // ***** Object interface ***** /** Allocates and default constructs an instance of T. Only default construction supported. */ template T* allocObject() { return new (allocObjectNoCon()) T(); } /** Allocates memory for an instance of T. No construction is performed. */ template T* allocObjectNoCon() { return static_cast(alloc(sizeof(T))); } /** Destructs *ptr and then frees it as a memory buffer. That buffer must be the most recently allocated buffer from this Arena that has not yet been freed. Double frees are not allowed. ptr must not be null. */ template void freeTopObject(T* ptr) { ptr->~T(); freeTop(ptr); } /** Destructs *ptr and then frees it as a memory buffer along with all not yet freed allocations that have happened since that buffer was allocated. ptr must not be null. */ template void freeObjectAndAllAfter(T* ptr) { ptr->~T(); freeAndAllAfter(ptr); } // ***** Array interface ***** /** As alloc(elementCount * sizeof(T)). Constructors for the elements of the array are not called. */ template std::pair allocArrayNoCon(size_t elementCount); /** As allocArrayNoCon except that constructors for the elements of the array are called. The constructors are called in increasing order of index. Constructed objects are destructed in reverse order if a constructor throws an exception. */ template std::pair allocArray(size_t elementCount); /** As freeTop(array) except that the elements of the array in the range (array, arrayEnd] are deconstructed in decreasing order of index. The destructors must not throw exceptions. array and arrayEnd must not be zero. */ template void freeTopArray(T* array, T* arrayEnd); /** As freeTopArray(p.first, p.second). */ template void freeTopArray(std::pair p) {freeTopArray(p.first, p.second);} /** As freeAndAllAfter(array) except that the elements of the array in the range (array, arrayEnd] are deconstructed in decreasing order of index. The destructors must not throw exceptions. */ template void freeArrayAndAllAfter(T* array, T* arrayEnd); /** As freeTopArrayAndAllAfter(p.first, p.second). */ template void freeArrayAndAllAfter(std::pair p) { freeArrayAndAllAfter(p.first, p.second); } // ***** RAII handles ***** // These would work much better with the features of C++11 // but C++11 is not yet available everywhere. template class PtrNoConNoDecon { public: PtrNoConNoDecon(Arena& arena): mArena(arena), mPtr(arena.allocObjectNoCon()) {} ~PtrNoConNoDecon() {mArena.freeTop(mPtr);} T* operator->() {return mPtr;} T const* operator->() const {return mPtr;} T* get() {return mPtr;} T const* get() const {return mPtr;} T& operator*() {return *mPtr;} T const& operator*() const {return *mPtr;} private: PtrNoConNoDecon(const PtrNoConNoDecon&); // not available void operator=(const PtrNoConNoDecon&); // not available Arena& mArena; T* const mPtr; }; // In the destructor, frees all allocations made since the // constructor unless the guard has been released. The most recent // allocation at the point of the constructor must not have been // freed at the point of the destructor -- this restriction only // applies if the guard has not been released. class Guard { public: Guard(Arena& arena): mArena(&arena), mPosition(arena.guardPoint()) {} ~Guard() { if (mArena != 0) mArena->restoreToGuardPoint(mPosition); } void release() {mArena = 0;} private: Arena* mArena; // guard has been released if null void* mPosition; }; // ***** Miscellaneous ***** /** Returns true if ptr is within the range of any memory buffer that has been allocated from this arena and that has not yet been deallocated. Pointers that are one-past-the-end of an allocated buffer are not within the range, but they may be inside a subsequent buffer and so may still yield a return value of true. Also, the allocated range may be larger than requested due to alignment in which case the pointer that is one-past-the-end would be inside the range. This method is useful for debugging and testing. */ bool fromArena(void const* ptr); /** Returns true if there are no live allocations for this Arena. */ inline bool isEmpty() const; /** Returns the total amount of memory allocated by this object. Includes excess capacity that has not been allocated by a client yet. Does NOT include memory for a DEBUG-only mechanism to catch bugs. */ size_t getMemoryUse() const {return _blocks.getMemoryUse();} /** Returns the total amount of memory allocated by this object to clients. Does not include excess capacity that is not currently allocated by a client. Does not include memory for a DEBUG-only mechanism to catch bugs. */ size_t getAllocatedMemoryUse() const {return _blocks.getMemoryUseToLeft();} /** Returns an arena object that can be used for non-thread safe scratch memory after static objects have been initialized. The default contract is that each function leaves this arena with the exact same objects allocated as before the function was entered. It is fine for functions to collaborate for example by using the arena to return variable size objects without calling new, though care should be used in such cases. */ static Arena& getArena() {return _scratchArena;} private: Arena(const Arena&); // not available void operator=(Arena&); // not available typedef MemoryBlocks::Block Block; Block& block() {return _blocks.getFrontBlock();} const Block& block() const {return _blocks.getFrontBlock();} /** Allocate a new block with at least needed bytes and at least double the capacity of the current block. */ void growCapacity(size_t needed); /** As freeTop where ptr was allocated from an old block. */ void freeTopFromOldBlock(void* ptr); /** As freeAndAllAfter where ptr was allocated from an old block. */ void freeAndAllAfterFromOldBlock(void* ptr); /** Obtain current state so that it can be restored later. The guard point is invalidated if the most recent allocation at the point this method is called is freed. */ void* guardPoint(); /** As freeAndAllAfter except that there need not be an allocation of ptr - it is just a position that the arena had in the past. */ void restoreToGuardPoint(void* ptr); MemoryBlocks _blocks; #ifdef MEMT_DEBUG std::vector _debugAllocs; #endif static Arena _scratchArena; }; inline bool Arena::isEmpty() const { return !block().hasPreviousBlock() && block().empty(); } inline void* Arena::alloc(size_t size) { // It is OK to check capacity before aligning size as capacity is aligned. // This single if checks for three different special circumstances: // * size is 0 (size - 1 will overflow) // * there is not enough capacity (size > capacity) // * aligning size would cause an overflow (capacity is aligned) const size_t capacity = block().getBytesToRight(); MEMT_ASSERT(capacity % MemoryAlignment == 0); if (size - 1 >= capacity) { MEMT_ASSERT(size == 0 || size > capacity); if (size == 0) { size = 1; if (capacity > 0) goto capacityOK; } growCapacity(size); } capacityOK: MEMT_ASSERT(0 < size); MEMT_ASSERT(size <= block().getBytesToRight()); MEMT_ASSERT(MemoryBlocks::alignNoOverflow(size) <= block().getBytesToRight()); char* ptr = block().position(); block().setPosition(ptr + MemoryBlocks::alignNoOverflow(size)); #ifdef MEMT_DEBUG _debugAllocs.push_back(ptr); #endif return ptr; } inline void Arena::freeTop(void* ptr) { MEMT_ASSERT(ptr != 0); #ifdef MEMT_DEBUG MEMT_ASSERT(!_debugAllocs.empty()); MEMT_ASSERT(_debugAllocs.back() == ptr); _debugAllocs.pop_back(); #endif if (!block().empty()) block().setPosition(ptr); else freeTopFromOldBlock(ptr); } inline void Arena::freeAndAllAfter(void* ptr) { MEMT_ASSERT(ptr != 0); #ifdef MEMT_DEBUG while (!_debugAllocs.empty() && ptr != _debugAllocs.back()) _debugAllocs.pop_back(); MEMT_ASSERT(!_debugAllocs.empty()); MEMT_ASSERT(_debugAllocs.back() == ptr); _debugAllocs.pop_back(); #endif if (block().isInBlock(ptr)) block().setPosition(ptr); else freeAndAllAfterFromOldBlock(ptr); } template std::pair Arena::allocArrayNoCon(size_t elementCount) { if (elementCount > static_cast(-1) / sizeof(T)) throw std::bad_alloc(); const size_t size = elementCount * sizeof(T); MEMT_ASSERT(size / sizeof(T) == elementCount); char* buffer = static_cast(alloc(size)); T* array = reinterpret_cast(buffer); T* arrayEnd = reinterpret_cast(buffer + size); return std::make_pair(array, arrayEnd); } template std::pair Arena::allocArray(size_t elementCount) { std::pair p = allocArrayNoCon(elementCount); T* it = p.first; try { for (; it != p.second; ++it) { new (it) T(); } } catch (...) { freeTopArray(p.first, it); throw; } return p; } template void Arena::freeTopArray(T* array, T* arrayEnd) { MEMT_ASSERT(array != 0); MEMT_ASSERT(array <= arrayEnd); while (arrayEnd != array) { --arrayEnd; arrayEnd->~T(); } freeTop(array); } template void Arena::freeArrayAndAllAfter(T* array, T* arrayEnd) { MEMT_ASSERT(array != 0); MEMT_ASSERT(array <= arrayEnd); while (arrayEnd != array) { --arrayEnd; arrayEnd->~T(); } freeAndAllAfter(array); } inline void* Arena::guardPoint() { // Supporting guard points is significantly more tricky than it // may at first seem. Do not alter guardPoint() and // restoreToGuardPoint() unless you are certain you understand the // code completely and have carefully considered the change. // // We cannot allow the guard point to be inside an empty block // since such blocks can be deallocated and that memory could then // potentially be somewhere inside a later-allocated block. This // problem does not appear for a non-empty block because the guard // point is invalidated if any of the allocations in that block // are later freed. if (!block().empty()) { MEMT_ASSERT_NO_ASSUME(!_debugAllocs.empty()); MEMT_ASSERT_NO_ASSUME(block().isInBlock(_debugAllocs.back())); MEMT_ASSERT_NO_ASSUME(_debugAllocs.back() < block().position()); return block().position(); // no problems in this case } if (block().hasPreviousBlock()) { // The previous block is not empty as then it would have been // deallocated, so it is safe to take the guard point from the // previous block. MEMT_ASSERT(!block().previousBlock()->empty()); MEMT_ASSERT_NO_ASSUME(!_debugAllocs.empty()); MEMT_ASSERT_NO_ASSUME (block().previousBlock()->isInBlock(_debugAllocs.back())); MEMT_ASSERT_NO_ASSUME (_debugAllocs.back() < block().previousBlock()->position()); return block().previousBlock()->position(); } else { // Here the arena is empty, so there is no non-empty block. MEMT_ASSERT(isEmpty()); MEMT_ASSERT_NO_ASSUME(_debugAllocs.empty()); // Return null to indicate empty arena. return 0; } } inline void Arena::restoreToGuardPoint(void* ptr) { if (ptr == static_cast(0)) { // null indicates empty arena freeAllAllocs(); return; } Block* b = &block(); while (!(b->begin() < ptr && ptr <= b->end())) { b->setPosition(b->begin()); b = b->previousBlock(); // If you get an assert here then most likely the guard point was // invalidated by deallocating memory that was live at the point // the guard point was created. MEMT_ASSERT(b != 0); } MEMT_ASSERT(b->begin() < ptr && ptr <= b->end()); b->setPosition(ptr); #ifdef MEMT_DEBUG // update _debugAllocs // there is always at least one allocation in the block of the // guard ptr, so _debugAllocs will have a pointer in that block. while (!_debugAllocs.empty() && !b->isInBlock(_debugAllocs.back())) _debugAllocs.pop_back(); MEMT_ASSERT(!_debugAllocs.empty()); while (!_debugAllocs.empty() && _debugAllocs.back() >= ptr) { MEMT_ASSERT(b->isInBlock(_debugAllocs.back())); _debugAllocs.pop_back(); } MEMT_ASSERT(!_debugAllocs.empty()); MEMT_ASSERT(b->isInBlock(_debugAllocs.back())); MEMT_ASSERT(_debugAllocs.back() < ptr); #endif } } #endif memtailor-master/src/memtailor/ArenaVector.h000077500000000000000000000036271220120200300214730ustar00rootroot00000000000000/* Copyright (C) 2011 Bjarke Hammersholt Roune (www.broune.com) MemTailor is distributed under the Modified BSD License. See license.txt. */ #ifndef MEMT_ARENA_VECTOR_GUARD #define MEMT_ARENA_VECTOR_GUARD #include "stdinc.h" #include "Arena.h" namespace memt { /** Works as std::vector, except it cannot grow its capacity and the memory is taken from an Arena. Only frees its memory on destruction if FreeMemory is true. In that case that memory must be the top allocation on the Arena. Always calls the destructors of contained entries even when FreeMemory is false. */ template class ArenaVector { public: typedef T* iterator; typedef const T* const_iterator; typedef T& reference; typedef const T& const_reference; typedef T value_type; ArenaVector(Arena& arena, size_t capacity); ~ArenaVector() { clear(); if (FreeMemory) _arena->freeTop(_begin); } bool empty() const {return _begin == _end;} size_t size() const {return _end - _begin;} T* begin() {return _begin;} const T* begin() const {return _begin;} T* end() {return _end;} const T* end() const {return _end;} void push_back(const T& t) { MEMT_ASSERT_NO_ASSUME(_end != _capacityEndDebug); new (_end) T(t); ++_end; } void pop_back() { MEMT_ASSERT(!empty()); --_end; _end->~T(); } void clear() { while (!empty()) pop_back(); } private: T* _begin; T* _end; Arena* _arena; /// @todo: only store if freeing memory #ifdef MEMT_DEBUG T* _capacityEndDebug; #endif }; template ArenaVector::ArenaVector(Arena& arena, size_t capacity) { _begin = arena.allocArrayNoCon(capacity).first; _end = _begin; _arena = &arena; #ifdef MEMT_DEBUG _capacityEndDebug = _begin + capacity; #endif } } #endif memtailor-master/src/memtailor/BufferPool.cpp000077500000000000000000000032631220120200300216540ustar00rootroot00000000000000/* Copyright (C) 2011 Bjarke Hammersholt Roune (www.broune.com) MemTailor is distributed under the Modified BSD License. See license.txt. */ #include "BufferPool.h" #include #include #include namespace memt { BufferPool::BufferPool(size_t bufferSize): _bufferSize(MemoryBlocks::alignThrowOnOverflow( std::max(bufferSize, sizeof(FreeNode)))), _free(0), _blocks() { } void BufferPool::growCapacity() { // ** Calcuate size of block (doubles capacity) size_t size = block().getBytesInBlock(); if (size == 0) { // start out at 10 buffers MEMT_ASSERT(block().isNull()); if (_bufferSize > std::numeric_limits::max() / 10) throw std::bad_alloc(); // _bufferSize * 10 overflows size = _bufferSize * 10; } else { // double the size if (size > std::numeric_limits::max() / 2) throw std::bad_alloc(); // size * 2 overflows size *= 2; } // ** Allocate next block MEMT_ASSERT(MemoryBlocks::alignNoOverflow(size) == size); MEMT_ASSERT(size > block().getBytesInBlock()); _blocks.allocBlock(size); } void BufferPool::freeAllBuffers() { _free = 0; _blocks.freeAllPreviousBlocks(); } void BufferPool::freeAllBuffersAndBackingMemory() { _free = 0; _blocks.freeAllBlocks(); } bool BufferPool::fromPool(const void* ptr) const { MemoryBlocks::Block const* block = _blocks.blockOf(ptr); if (block == 0) return false; #ifdef MEMT_DEBUG const size_t offset = static_cast(static_cast(ptr) - block->begin()); MEMT_ASSERT(offset % _bufferSize == 0); // otherwise not a valid pointer #endif return true; } } memtailor-master/src/memtailor/BufferPool.h000077500000000000000000000104321220120200300213150ustar00rootroot00000000000000/* Copyright (C) 2011 Bjarke Hammersholt Roune (www.broune.com) MemTailor is distributed under the Modified BSD License. See license.txt. */ #ifndef MEMT_BUFFER_POOL_GUARD #define MEMT_BUFFER_POOL_GUARD #include "stdinc.h" #include "MemoryBlocks.h" #include namespace memt { /** Allocator for allocating and freeing same-size buffers. Uses a free list. All allocations are automatically freed when the buffer pool is destructed. */ class BufferPool { public: BufferPool(BufferPool&& pool); /** bufferSize is how many bytes are returned by each call to alloc. */ BufferPool(size_t bufferSize); /** Returns a pointer to an array of getBufferSize() chars. The alignment is as for Arena. The lifetime of the buffer is until free is called with the returned value as parameter on this same object or clear() is called or this object is destructed. Do not pass the returned value to ::free, do not delete it and do not free it on a different BufferPool. Throws an exception if no more memory can be allocated. Never returns null. */ inline void* alloc(); /** Makes the buffer at ptr available for reuse. ptr must be a value previously returned by alloc on this same object that hasn't been freed already since then. ptr must not be null. This method cannot throw an exception. */ inline void free(void* ptr); /** Returns how many bytes are in each buffer. Can be a few bytes more than requested due to internal requirements on the size of the buffers. Will never be less than requested. */ size_t getBufferSize() const {return _bufferSize;} /** Frees all allocated buffers. Does not deallocate all the internal backing memory, but may deallocate some of it. */ void freeAllBuffers(); /** Frees all allocated buffers and frees all internal backing memory too. */ void freeAllBuffersAndBackingMemory(); /** Returns the total amount of memory currently allocated by this object. Includes excess capacity that has not been allocated to a client yet. */ size_t getMemoryUse() const {return _blocks.getMemoryUse();} /** Returns true if ptr is inside the memory area internally allocated by this BufferPool. Only call this method on a valid pointer. Note that pointers that have been allocated and then freed on a pool are not guaranteed to be valid as the internal backing memory could have been deallocated. The intended use for this method is to assert that a given valid pointer has been allocated from a given pool. It could also be used to determine which of several pools a non-freed pointer comes from, though needing to make this determination probably indicates a design problem. This method runs in logarithmic time in the maximum number of allocations that have been live at the same time for this pool. */ bool fromPool(const void* ptr) const; private: BufferPool(const BufferPool&); // not available void operator=(const BufferPool&); // not available typedef MemoryBlocks::Block Block; Block& block() {return _blocks.getFrontBlock();} const Block& block() const {return _blocks.getFrontBlock();} /** Allocate another block of double the size. */ void growCapacity(); /** A node of the linked list of free buffers. */ struct FreeNode { FreeNode* next; }; const size_t _bufferSize; /// size of the buffers returned by alloc FreeNode* _free; /// null indicates that the free list is empty MemoryBlocks _blocks; /// internal backing memory }; inline BufferPool::BufferPool(BufferPool&& pool): _bufferSize(pool._bufferSize), _free(pool._free), _blocks(std::move(pool._blocks)) { pool._free = 0; } inline void* BufferPool::alloc() { void* ptr; if (_free != 0) { ptr = _free; _free = _free->next; } else { if (block().position() == block().end()) growCapacity(); ptr = block().position(); block().setPosition(block().position() + getBufferSize()); } return ptr; } inline void BufferPool::free(void* ptr) { MEMT_ASSERT(ptr != 0); MEMT_ASSERT(fromPool(ptr)); FreeNode* node = reinterpret_cast(ptr); node->next = _free; _free = node; } } #endif memtailor-master/src/memtailor/MemoryBlocks.cpp000077500000000000000000000046041220120200300222170ustar00rootroot00000000000000/* Copyright (C) 2011 Bjarke Hammersholt Roune (www.broune.com) MemTailor is distributed under the Modified BSD License. See license.txt. */ #include "MemoryBlocks.h" namespace memt { void MemoryBlocks::freeAllPreviousBlocks() { while (_block.hasPreviousBlock()) freePreviousBlock(); } void MemoryBlocks::freeAllBlocks() { freeAllPreviousBlocks(); _block.free(); _block.makeNull(); } void MemoryBlocks::Block::newBlock(size_t capacityInBytes) { if (!isNull()) { // We set aside space for a block at the end of the memory. Use that // space to store the block for the old memory. const size_t blockStructOffset = alignNoOverflow(getBytesInBlock()); Block* block = reinterpret_cast(begin() + blockStructOffset); block->_previous = this->previousBlock(); block->_begin = begin(); block->_end = end(); block->_position = position(); _previous = block; } // make space for block information at end of new memory, but do not // use it yet. const size_t aligned = alignThrowOnOverflow(capacityInBytes); const size_t total = aligned + sizeof(Block); if (total < aligned) // check overflow throw std::bad_alloc(); _begin = new char[total]; _position = _begin; _end = _begin + capacityInBytes; MEMT_ASSERT(!isNull()); MEMT_ASSERT(empty()); MEMT_ASSERT(capacityInBytes == getBytesInBlock()); } size_t MemoryBlocks::getMemoryUse() const { size_t sum = 0; const Block* block = &_block; do { sum += block->getBytesInBlock(); block = block->previousBlock(); } while (block != 0); return sum; } size_t MemoryBlocks::getMemoryUseToLeft() const { size_t sum = 0; const Block* block = &_block; do { sum += block->getBytesToLeft(); block = block->previousBlock(); } while (block != 0); return sum; } void MemoryBlocks::Block::freePrevious() { MEMT_ASSERT(hasPreviousBlock()); Block* previousPrevious = previousBlock()->previousBlock(); previousBlock()->free(); _previous = previousPrevious; } MemoryBlocks::Block* MemoryBlocks::blockOf(const void* ptr) { if (ptr == 0) return 0; // avoid saying that null is in a null block Block* block = &_block; do { if (block->isInBlock(ptr)) return block; block = block->previousBlock(); } while (block != 0); return 0; } } memtailor-master/src/memtailor/MemoryBlocks.h000077500000000000000000000213641220120200300216660ustar00rootroot00000000000000/* Copyright (C) 2011 Bjarke Hammersholt Roune (www.broune.com) MemTailor is distributed under the Modified BSD License. See license.txt. */ #ifndef MEMT_MEMORY_BLOCKS_GUARD #define MEMT_MEMORY_BLOCKS_GUARD #include "stdinc.h" #include #include namespace memt { /** Handles a linked list of blocks of memory. Intended for use in implementing other memory allocators. */ class MemoryBlocks { public: class Block; /// Moves ownership of data and leaves the parameter in a /// valid empty state. MemoryBlocks(MemoryBlocks&& blocks); /** Makes the front block a null block object. No memory is allocated. */ MemoryBlocks() {} /** Makes the front block have the given capacity. */ MemoryBlocks(size_t capacityInBytes) {allocBlock(capacityInBytes);} /** Frees all blocks. */ ~MemoryBlocks() {freeAllBlocks();} /** Create a new front block with the given capacity. If the previous front block is not null, it becomes the previous block of the new front block. This invalidates all block pointers. */ Block& allocBlock(size_t capacityInBytes); /** Frees the block previous to the front block. The block before that, if any, becomes the new front block. There must be a previous block to call this method. */ void freePreviousBlock() {_block.freePrevious();} /** Frees all blocks except the front block which is not changed. */ void freeAllPreviousBlocks(); /** Frees all blocks including the front block. The new front block will be a null block object. */ void freeAllBlocks(); /** Returns the current front block. Can be a null block object. */ Block& getFrontBlock() {return _block;} /** Returns the current front block. Can be a null block object. */ Block const& getFrontBlock() const {return _block;} /** Returns true if ptr is in some block of this object. Blocks that have been freed do not count. Note that stray pointers may randomly happen to hit a block. */ bool inSomeBlock(void* ptr) const {return blockOf(ptr) != 0;} /** Returns the block that contains ptr, or null if there is no such block. Always returns null if ptr is null, even though strictly speaking a null pointer will be in the range of a null block. */ Block* blockOf(const void* ptr); const Block* blockOf(const void* ptr) const { return const_cast(*this).blockOf(ptr); } /** Returns the total amount of memory allocated by this object. */ size_t getMemoryUse() const; /** Returns the total amount of memory in the left parts of the blocks of this object. */ size_t getMemoryUseToLeft() const; /** Rounds value up to the nearest multiple of MemoryAlignment. This rounded up value must be representable in a size_t. */ inline static size_t alignNoOverflow(size_t value); /** Rounds value up to the nearest multiple of MemoryAlignment. Throw std::bad_alloc if this rounded up value is not representable in a size_t. */ inline static size_t alignThrowOnOverflow(size_t value); /** A block owns a range of memory [begin(), end()) and keeps track of a position within the range [begin(), end()] given by position(). It is possible for a block to own no memory, in which case begin(), end() and position are null - we call this a null block object. Do not create your own blocks - their lifetime is handled by MemoryBlocks. */ class Block { public: char* begin() {return _begin;} char const* begin() const {return _begin;} char* end() {return _end;} char const* end() const {return _end;} char* position() {return _position;} char const* position() const {return _position;} inline void setPosition(const void* position); /** Returns true if ptr is in the range [begin(), end()). Be aware that this implies that the return value is true when ptr is null and the block is a null. */ inline bool isInBlock(const void* ptr) const; /** Returns the number of bytes in the range [begin(), end()). */ size_t getBytesInBlock() const {return _end - _begin;} /** Returns the number of bytes in the range [position(), end()). */ size_t getBytesToRight() const {return _end - _position;} /** Returns the number of bytes in the range [begin(), position()). */ size_t getBytesToLeft() const {return _position - _begin;} /** Returns true if position() == begin(). */ bool empty() const {return position() == begin();} Block* previousBlock() {return _previous;} Block const* previousBlock() const {return _previous;} /** Returns true if previousBlock() is not null. */ bool hasPreviousBlock() const {return _previous != 0;} /** Returns true this is a null block object. That is, if begin(), end() and position() are all null. */ bool isNull() const {return begin() == 0;} /** Sets position to begin(). */ void clear() {setPosition(begin());} private: friend class MemoryBlocks; /// Moves ownership of memory and leaves block in a valid null state. Block(Block&& block): _begin(block._begin), _position(block._position), _end(block._end), _previous(block._previous) { block.makeNull(); } Block() {makeNull();} Block(size_t capacity, Block* previous); Block(Block const&); // unavailable void operator=(Block const&); // unavailable /// Makes this a null block object. Does NOT free the owned memory! void makeNull() { _previous = 0; _begin = 0; _position = 0; _end = 0; } /** Frees the memory for this block. */ void free() {delete[] begin();} /** Frees the memory for the previous block. */ void freePrevious(); /** Makes new memory for this block and puts the old memory in a block previous to this block. */ void newBlock(size_t capacity); char* _begin; /// beginning of current block (aligned) char* _position; /// pointer to first free byte (aligned) char* _end; /// one past last byte (aligned) Block* _previous; /// null if no previous block }; private: MemoryBlocks(const MemoryBlocks&); // not available void operator=(const MemoryBlocks&); // not available Block _block; }; inline MemoryBlocks::MemoryBlocks(MemoryBlocks&& blocks): _block(std::move(blocks._block)) {} inline MemoryBlocks::Block& MemoryBlocks::allocBlock(size_t capacityInBytes) { _block.newBlock(capacityInBytes); return _block; } inline void MemoryBlocks::Block::setPosition(void const* position) { MEMT_ASSERT(position == end() || isInBlock(position)); _position = const_cast(reinterpret_cast(position)); } inline size_t MemoryBlocks::alignNoOverflow(const size_t value) { // this function might look big, but the total compiled code size is // one addition and one bitwise and. const size_t decAlign = MemoryAlignment - 1; // compile time constant MEMT_ASSERT((MemoryAlignment & (decAlign)) == 0); // power of 2 // This works because MemoryAlignment is a power of 2. const size_t aligned = (value + decAlign) & (~decAlign); MEMT_ASSERT(aligned % MemoryAlignment == 0); // alignment MEMT_ASSERT(aligned >= value); // no overflow MEMT_ASSERT(aligned - value < MemoryAlignment); // adjustment minimal return aligned; } inline size_t MemoryBlocks::alignThrowOnOverflow(size_t value) { // this function might look big, but the total compiled code size is // one addition, one branch using a comparison and one bitwise and. const size_t decAlign = MemoryAlignment - 1; // compile time constant MEMT_ASSERT((MemoryAlignment & (decAlign)) == 0); // power of 2 // This sum overflows if and only if rounding up overflows because // MemoryAlignment is a power of 2. const size_t sum = value + decAlign; if (sum < value) throw std::bad_alloc(); // overflow const size_t aligned = sum & (~decAlign); MEMT_ASSERT(aligned % MemoryAlignment == 0); // alignment MEMT_ASSERT(aligned >= value); // no overflow MEMT_ASSERT(aligned - value < MemoryAlignment); // adjustment minimal return aligned; } inline bool MemoryBlocks::Block::isInBlock(const void* ptr) const { // We use a trick to check this using one branch and two subtractions // instead of two branches. const char* p = static_cast(ptr); const size_t offset = static_cast(p - begin()); // if _blockBegin > ptr then offset overflows to a large integer MEMT_ASSERT((offset < getBytesInBlock()) == (begin() <= p && p < end())); return offset < getBytesInBlock(); } } #endif memtailor-master/src/memtailor/stdinc.h000077500000000000000000000072731220120200300205470ustar00rootroot00000000000000/* Copyright (C) 2011 Bjarke Hammersholt Roune (www.broune.com) MemTailor is distributed under the Modified BSD License. See license.txt. */ #ifndef MEMT_STDINC_GUARD #define MEMT_STDINC_GUARD #ifdef _MSC_VER // For Microsoft Compiler in Visual Studio C++. // Sometimes you know that a function will be called very rarely so you want to // tell the compiler not to inline it even if it could be inlined at only a // modest increase in code size. That is what MEMT_NO_INLINE does. #define MEMT_NO_INLINE __declspec(noinline) // Sometimes the compiler just will not inline functions that should // be inlined. Use sparingly --- preferably only if a profiler says // that a tiny often-called function consumes a significant amount of time. #define MEMT_INLINE __forceinline // Tells the compiler to always assume that the expression X is true. #define MEMT_ASSUME(X) __assume(X) // As MEMT_ASSUME, but might actually evaluate X at run-time if it has // side-effects. The point is that this can be used on compilers with no other // support for assuming things. So there is no difference on MS VC++. #define MEMT_ASSUME_AND_MAY_EVALUATE(X) __assume(X) // Tells the compiler that this function returns a pointer that is not an alias // for any other point that is currently valid in the program - like malloc. #define MEMT_RETURN_NO_ALIAS __declspec(restrict) // Tells the compiler that this function will never throw an exception. #define MEMT_NOTHROW __declspec(nothrow) // Tells the compiler that this function has no effects except the return value // and the return value depends only on the arguments and first-level // indirections of the arguments. (this is the common denominator of GCC // and MS VC++ capabilities) #define MEMT_PURE __declspec(noalias) // Tells the compiler that the return value of this function must be looked // at by the caller. For example this is appropriate for realloc. #define MEMT_MUST_CHECK_RETURN_VALUE // Tells the compiler that the current line of code cannot be reached. #define MEMT_UNREACHABLE __assume(false) // Tells the compiler that a variable that is a pointer (not a reference) // does not alias any other pointer that is used in the current scope. #define MEMT_RESTRICT __restrict #elif defined (__GNUC__) // GCC compiler #define MEMT_NO_INLINE __attribute__((noinline)) #define MEMT_INLINE __attribute__((always_inline)) inline #define MEMT_ASSUME(X) #define MEMT_ASSUME_AND_MAY_EVALUATE(X) do {if(!(X)){MEMT_UNREACHABLE;}while(0)} #define MEMT_RETURN_NO_ALIAS __attribute__(malloc) #define MEMT_NOTHROW __attribute__(nothrow) #define MEMT_PURE __attribute__(pure) #define MEMT_MUST_CHECK_RETURN_VALUE __attribute__(warn_unused_result) #define MEMT_UNREACHABLE __builtin_unreachable() #else #define MEMT_NO_INLINE #define MEMT_INLINE inline #define MEMT_ASSUME(X) #define MEMT_ASSUME_AND_MAY_EVALUATE(X) #define MEMT_RETURN_NO_ALIAS #define MEMT_NOTHROW #define MEMT_PURE #define MEMT_MUST_CHECK_RETURN_VALUE #define MEMT_UNREACHABLE #endif #ifdef MEMT_SLOW_DEBUG // for asserts that take a long time. #define MEMT_SLOW_ASSERT(X) MEMT_ASSERT(X) #ifndef MEMT_DEBUG #define MEMT_DEBUG #endif #else #define MEMT_SLOW_ASSERT(X) #endif #ifdef MEMT_DEBUG #include #define MEMT_ASSERT(X) do{assert(X);}while(0) #define MEMT_ASSERT_NO_ASSUME(X) MEMT_ASSERT(X) #else #define MEMT_ASSERT(X) MEMT_ASSUME(X) #define MEMT_ASSERT_NO_ASSUME(X) #endif namespace memt { /// The alignment that memory allocators must ensure. In other words /// allocators must return pointer addresses that are divisible by /// MemoryAlignment. MemoryAlignment must be a power of 2. static const unsigned int MemoryAlignment = sizeof(void*); static const unsigned int BitsPerByte = 8; } #endif memtailor-master/src/test/000077500000000000000000000000001220120200300160645ustar00rootroot00000000000000memtailor-master/src/test/ArenaTest.cpp000077500000000000000000000200741220120200300204640ustar00rootroot00000000000000/* Frobby: Software for monomial ideal computations. Copyright (C) 2011 University of Aarhus Contact Bjarke Hammersholt Roune for license information (www.broune.com) 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, see http://www.gnu.org/licenses/. */ #include #include #include #include TEST(Arena, NoOp) { memt::Arena arena; } TEST(Arena, GetMemoryUsage) { memt::Arena arena; ASSERT_EQ(arena.getMemoryUse(), 0); arena.alloc(100); ASSERT_TRUE(arena.getMemoryUse() >= 100); } TEST(Arena, Big) { memt::Arena arena; void* a = arena.alloc(5); arena.freeTop(arena.alloc(1024 * 1024)); arena.freeTop(arena.alloc(1024 * 1024)); ASSERT_FALSE(arena.isEmpty()); arena.freeTop(a); ASSERT_TRUE(arena.isEmpty()); } TEST(Arena, Zero) { memt::Arena arena; void* a = arena.alloc(0); void* b = arena.alloc(0); void* c = arena.alloc(0); ASSERT_NE(a, b); ASSERT_NE(a, c); ASSERT_NE(b, c); ASSERT_FALSE(arena.isEmpty()); } TEST(Arena, Many) { memt::Arena arena; std::vector > allocs; for (size_t i = 3; i < 10; ++i) { for (size_t size = 0; size < 100; ++size) { char* a = static_cast(arena.alloc(size)); std::pair p(a, a + size); for (size_t j = 0; j < allocs.size(); ++j) { std::pair p2 = allocs[j]; if (p.first <= p2.first) ASSERT_FALSE(p2.first < p.second); else ASSERT_FALSE(p.first < p2.second); } std::fill(p.first, p.second, static_cast(-1)); allocs.push_back(p); } while (allocs.size() > 10 * i) { arena.freeTop(allocs.back().first); allocs.pop_back(); } arena.freeAndAllAfter(allocs[5 * i].first); allocs.resize(5 * i); } ASSERT_FALSE(arena.isEmpty()); arena.freeAndAllAfter(allocs.front().first); ASSERT_TRUE(arena.isEmpty()); } TEST(Arena, BigAndOverflow) { memt::Arena arena; // aligning size causes overflow ASSERT_THROW(arena.alloc(static_cast(-1)), std::bad_alloc); // 2x size is an overflow ASSERT_THROW(arena.alloc(static_cast(-1)/2 + 1), std::bad_alloc); // causes attempt at allocating almost the entire virtual memory space // which cannot succeed ASSERT_THROW(arena.alloc(static_cast(-1)/2 - 100), std::bad_alloc); // sizeof(long) * x overflows to a smaller value (0). const size_t smallerOverflow = 1ul << (8*sizeof(long) - 1); MEMT_ASSERT(smallerOverflow > 0); //ASSERT(smallerOverflow * sizeof(long) == 0); compiler warning ASSERT_THROW(arena.allocArray(smallerOverflow), std::bad_alloc); // sizeof(int) * x overflows to a greater value const size_t greaterOverflow = (~(0ul)) >> 1; MEMT_ASSERT(sizeof(long) >= 4); //ASSERT(greaterOverflow * sizeof(long) > greaterOverflow); compiler warning //ASSERT(greaterOverflow != (greaterOverflow * sizeof(long)) / sizeof(long)); ASSERT_THROW(arena.allocArray(greaterOverflow), std::bad_alloc); ASSERT_TRUE(arena.isEmpty()); } // Make a class that keeps track of constructions and destructions in // a global string. MAKE_HELPER will make a separate instantiation for // every test so the tests are still independent in spite of the use // of global variables. This is also thread safe as long as two // threads are not running the same test at the same time. namespace { template class _frobby_Helper { public: _frobby_Helper() { _id = ++_count; if (_id == ThrowAt) { _log << 'T' << _id; throw _id; } else _log << '+' << _id; } ~_frobby_Helper() { _log << '-' << _id; } void setId(size_t id) {_id = id;} static std::string resetLog() { std::string log = _log.str(); _log.clear(); _log.str(""); _count = 0; return log; } private: size_t _id; static size_t _count; static std::ostringstream _log; }; template size_t _frobby_Helper::_count = 0; template std::ostringstream _frobby_Helper::_log; } #define MAKE_HELPER(NAME, THROW_AT) \ namespace { \ struct _frobby_##NAME##HelperTag {}; \ typedef _frobby_Helper<_frobby_##NAME##HelperTag, THROW_AT> NAME##Helper; \ } MAKE_HELPER(ConDecon, 0) TEST(Arena, ConDecon) { memt::Arena arena; arena.freeTopArray(arena.allocArray(0)); arena.freeTopArray(arena.allocArray(3)); arena.freeTopArray(arena.allocArray(0)); ASSERT_EQ(ConDeconHelper::resetLog(), "+1+2+3-3-2-1"); ASSERT_TRUE(arena.isEmpty()); } MAKE_HELPER(ConExcep, 4) TEST(Arena, ConExcep) { memt::Arena arena; ASSERT_THROW(arena.allocArray(10), size_t); ASSERT_EQ(ConExcepHelper::resetLog(), "+1+2+3T4-3-2-1"); ASSERT_TRUE(arena.isEmpty()); } MAKE_HELPER(NoConDecon, 0) TEST(Arena, NoConDecon) { memt::Arena arena; std::pair p = arena.allocArrayNoCon(3); p.first[0].setId(1); p.first[1].setId(2); p.first[2].setId(3); arena.freeTopArray(p); ASSERT_EQ(NoConDeconHelper::resetLog(), "-3-2-1"); ASSERT_TRUE(arena.isEmpty()); } MAKE_HELPER(ConNoDecon, 0) TEST(Arena, ConNoDecon) { memt::Arena arena; arena.freeTop(arena.allocArray(3).first); ASSERT_EQ(ConNoDeconHelper::resetLog(), "+1+2+3"); ASSERT_TRUE(arena.isEmpty()); } MAKE_HELPER(PtrNoConNoDecon, 0) TEST(Arena, PtrNoConNoDecon) { memt::Arena arena; ASSERT_TRUE(arena.isEmpty()); { memt::Arena::PtrNoConNoDecon ptr1(arena); ASSERT_FALSE(arena.isEmpty()); memt::Arena::PtrNoConNoDecon ptr2(arena); memt::Arena::PtrNoConNoDecon ptr3(arena); memt::Arena::PtrNoConNoDecon ptr4(arena); ASSERT_FALSE(arena.isEmpty()); } ASSERT_TRUE(arena.isEmpty()); ASSERT_EQ(PtrNoConNoDeconHelper::resetLog(), ""); } TEST(Arena, Guard) { memt::Arena arena; { memt::Arena::Guard noop(arena); // no-op guard } { // double no-op guard memt::Arena::Guard guard1(arena); memt::Arena::Guard guard2(arena); } // guard for empty arena with no allocations on it ever memt::Arena::Guard emptyGuard(arena); arena.freeTop(arena.alloc(10000)); // guard for empty arena which has allocated some memory previously memt::Arena::Guard emptyGuard2(arena); // memory use is exponential in number of iterations so do not // increase too much. void* fromIteration3 = 0; for (size_t i = 0; i < 6u; ++i) { if (i == 3) fromIteration3 = arena.alloc(1); { memt::Arena::Guard noop(arena); // no-op guard } void* tmp; { memt::Arena::Guard g1(arena); { memt::Arena::Guard g2(arena); tmp = arena.alloc(1); ASSERT_TRUE(arena.fromArena(tmp)); g2.release(); } ASSERT_TRUE(arena.fromArena(tmp)); // released guard did not free memt::Arena::Guard g3(arena); memt::Arena::Guard g4(arena); memt::Arena::Guard g5(arena); memt::Arena::Guard g6(arena); g6.release(); g3.release(); ASSERT_TRUE(arena.fromArena(tmp)); } ASSERT_FALSE(arena.fromArena(tmp)); // freed despite some guards freed // allocate enough memory to force a new block of backing memory // inside the arena. arena.alloc(arena.getMemoryUse()); } // free a middle allocation to force some blocks to go away ASSERT_TRUE(fromIteration3 != 0); ASSERT_TRUE(arena.fromArena(fromIteration3)); arena.freeAndAllAfter(fromIteration3); } memtailor-master/src/test/BufferPoolTest.cpp000077500000000000000000000050371220120200300215030ustar00rootroot00000000000000/* Frobby: Software for monomial ideal computations. Copyright (C) 2011 University of Aarhus Contact Bjarke Hammersholt Roune for license information (www.broune.com) 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, see http://www.gnu.org/licenses/. */ #include #include #include TEST(BufferPool, NoOp) { memt::BufferPool pool1(0); memt::BufferPool pool2(1); memt::BufferPool pool3(100); } TEST(BufferPool, FreeBuffers) { memt::BufferPool pool(5); for (size_t j = 0; j < 2; ++j) { pool.freeAllBuffers(); for (size_t i = 0; i < 100; ++i) { pool.free(pool.alloc()); pool.alloc(); } pool.freeAllBuffers(); } } TEST(BufferPool, GetMemoryUsage) { memt::BufferPool pool(100); ASSERT_EQ(pool.getMemoryUse(), 0); pool.alloc(); ASSERT_TRUE(pool.getMemoryUse() >= 100); } TEST(BufferPool, FreeBuffersAndBackingMemory) { memt::BufferPool pool(5); for (size_t j = 0; j < 2; ++j) { pool.freeAllBuffersAndBackingMemory(); for (size_t i = 0; i < 100; ++i) { pool.free(pool.alloc()); pool.alloc(); } pool.freeAllBuffersAndBackingMemory(); } } TEST(BufferPool, Grind) { memt::BufferPool pool(1001); std::list ptrs; for (size_t i = 0; i < 10; ++i) { for (size_t j = 0; j < 100; ++j) ptrs.push_back(pool.alloc()); // free most but not all and in FIFO order for (size_t j = 0; j < 90; ++j) { pool.free(ptrs.front()); ptrs.pop_front(); } } // free rest in LIFO order while (!ptrs.empty()) { pool.free(ptrs.back()); ptrs.pop_back(); } } TEST(BufferPool, SmallBuffers) { memt::BufferPool pools[] = {1, 2, 3, 4, 5}; for (size_t i = 0; i < sizeof(pools) / sizeof(memt::BufferPool); ++i) { memt::BufferPool& pool = pools[i]; void* a = pool.alloc(); pool.free(a); void* b = pool.alloc(); void* c = pool.alloc(); pool.alloc(); pool.free(c); for (size_t i = 0; i < 10000; ++i) pool.alloc(); pool.free(b); } } memtailor-master/src/test/MemoryBlocksTest.cpp000077500000000000000000000102271220120200300220430ustar00rootroot00000000000000/* Frobby: Software for monomial ideal computations. Copyright (C) 2011 University of Aarhus Contact Bjarke Hammersholt Roune for license information (www.broune.com) 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, see http://www.gnu.org/licenses/. */ #include #include #include #include TEST(MemoryBlocks, NoOp) { memt::MemoryBlocks blocks; ASSERT_TRUE(blocks.getMemoryUse() == 0); } TEST(MemoryBlocks, MemoryUsage) { const size_t MaxOverhead = sizeof(memt::MemoryBlocks::Block) + (memt::MemoryAlignment - 1); memt::MemoryBlocks blocks; ASSERT_EQ(blocks.getMemoryUse(), 0); blocks.allocBlock(100); ASSERT_TRUE(blocks.getMemoryUse() >= 100); ASSERT_TRUE(blocks.getMemoryUse() <= 100 + MaxOverhead); blocks.allocBlock(200); blocks.allocBlock(400); ASSERT_TRUE(blocks.getMemoryUse() >= 700); ASSERT_TRUE(blocks.getMemoryUse() <= 700 + 3 * MaxOverhead); blocks.freeAllPreviousBlocks(); ASSERT_TRUE(blocks.getMemoryUse() >= 400); ASSERT_TRUE(blocks.getMemoryUse() <= 400 + 3 * MaxOverhead); blocks.allocBlock(800); blocks.freeAllBlocks(); ASSERT_EQ(blocks.getMemoryUse(), 0); } TEST(MemoryBlocks, NoLeak) { memt::MemoryBlocks blocks1; blocks1.allocBlock(100); memt::MemoryBlocks blocks2; blocks2.allocBlock(100); blocks2.allocBlock(1); blocks2.allocBlock(0); // if run with a leak detector, this should pick up a leak if // blocks are not freed automatically. } TEST(MemoryBlocks, Properties) { memt::MemoryBlocks blocks; ASSERT_TRUE(blocks.getFrontBlock().isNull()); for (size_t i = 0; i <= 100; ++i) { memt::MemoryBlocks::Block& block = blocks.allocBlock(i); std::fill(block.begin(), block.end(), static_cast(i)); ASSERT_EQ(&block, &blocks.getFrontBlock()); ASSERT_FALSE(block.isNull()); ASSERT_EQ(block.position(), block.begin()); ASSERT_EQ(block.getBytesInBlock(), i); ASSERT_EQ(block.getBytesToRight(), i); ASSERT_EQ(block.end(), block.begin() + i); ASSERT_TRUE(block.empty()); block.setPosition(block.begin() + i / 2); if (i > 0) { ASSERT_EQ(block.position(), block.begin() + i / 2); if (i > 1) { ASSERT_FALSE(block.empty()); } ASSERT_TRUE(block.isInBlock(block.begin())); ASSERT_TRUE(block.isInBlock(block.end() - 1)); } else { ASSERT_EQ(block.begin(), block.end()); } ASSERT_EQ(block.getBytesToRight(), i - i / 2); ASSERT_FALSE(block.isInBlock(block.end())); ASSERT_FALSE(block.isInBlock(block.begin() - 1)); block.clear(); ASSERT_EQ(block.position(), block.begin()); ASSERT_TRUE(block.empty()); } for (size_t i = 100; i > 0; --i) { ASSERT_TRUE(blocks.getFrontBlock().hasPreviousBlock()); memt::MemoryBlocks::Block* previous = blocks.getFrontBlock().previousBlock(); for (const char* it = previous->begin(); it != previous->end(); ++it) ASSERT_EQ(*it, static_cast(i - 1)); ASSERT_EQ(previous->getBytesInBlock(), i - 1); blocks.freePreviousBlock(); } ASSERT_FALSE(blocks.getFrontBlock().isNull()); ASSERT_EQ(blocks.getFrontBlock().getBytesInBlock(), 100u); blocks.allocBlock(101); ASSERT_EQ(blocks.getFrontBlock().previousBlock()->getBytesInBlock(), 100u); blocks.allocBlock(102); ASSERT_EQ(blocks.getFrontBlock().previousBlock()->getBytesInBlock(), 101u); blocks.freeAllPreviousBlocks(); ASSERT_FALSE(blocks.getFrontBlock().isNull()); ASSERT_FALSE(blocks.getFrontBlock().hasPreviousBlock()); ASSERT_EQ(blocks.getFrontBlock().getBytesInBlock(), 102u); blocks.allocBlock(103); blocks.freeAllBlocks(); ASSERT_TRUE(blocks.getFrontBlock().isNull()); } memtailor-master/src/test/gtestInclude.cpp000077500000000000000000000010301220120200300212170ustar00rootroot00000000000000// Includes a file from gtest that pulls in all of the implementation // of gtest. The gtest docs recommend building gtest individually for // each program rather than using an installed gtest and this is as // easy a way of doing it as any. Especially because it guarantees that // the compiler flags are the same, which is the whole point of the // recommendation to build gtest for each program. // the .. goes back from the include/ directory of gtest so we can // enter the src directory. #include <../src/gtest-all.cc> memtailor-master/src/test/testMain.cpp000077500000000000000000000002021220120200300203510ustar00rootroot00000000000000#include int main(int argc, char **argv) { ::testing::InitGoogleTest(&argc, argv); return RUN_ALL_TESTS(); }