diff --git a/source/lib/allocators/arena.cpp b/source/lib/allocators/arena.cpp new file mode 100644 index 0000000000..b3f544458b --- /dev/null +++ b/source/lib/allocators/arena.cpp @@ -0,0 +1,75 @@ +/* Copyright (c) 2011 Wildfire Games + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * 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 AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY + * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +/* + * arena allocator (variable-size blocks, no deallocation). + */ + +#include "precompiled.h" +#include "lib/allocators/arena.h" + +namespace Allocators { + +template +struct BasicArenaTest +{ + void operator()() const + { + Arena a(100); + const size_t initialSpace = a.RemainingBytes(); + void* p = a.Allocate(100); + ENSURE(p != 0); + ENSURE(a.Contains(uintptr_t(p))); + ENSURE(a.RemainingBytes() == initialSpace-100); + ENSURE(a.Contains(uintptr_t(p)+1)); + ENSURE(a.Contains(uintptr_t(p)+99)); + ENSURE(!a.Contains(uintptr_t(p)-1)); + ENSURE(!a.Contains(uintptr_t(p)+100)); + if(a.RemainingBytes() == 0) + ENSURE(a.Allocate(1) == 0); // full + else + ENSURE(a.Allocate(1) != 0); // can still expand + a.DeallocateAll(); + ENSURE(!a.Contains(uintptr_t(p))); + + p = a.Allocate(36); + ENSURE(p != 0); + ENSURE(a.Contains(uintptr_t(p))); + ENSURE(a.RemainingBytes() == initialSpace-36); + void* p2 = a.Allocate(64); + ENSURE(p2 != 0); + ENSURE(a.Contains(uintptr_t(p2))); + ENSURE(a.RemainingBytes() == initialSpace-36-64); + ENSURE(p2 == (void*)(uintptr_t(p)+36)); + if(a.RemainingBytes() == 0) + ENSURE(a.Allocate(1) == 0); // full + else + ENSURE(a.Allocate(1) != 0); // can still expand + } +}; + +void TestArena() +{ + ForEachStorage(); +} + +} // namespace Allocators diff --git a/source/lib/allocators/arena.h b/source/lib/allocators/arena.h index fe5a323c40..379305e693 100644 --- a/source/lib/allocators/arena.h +++ b/source/lib/allocators/arena.h @@ -42,6 +42,7 @@ namespace Allocators { template class Arena { + NONCOPYABLE(Arena); public: Arena(size_t maxSize) : storage(maxSize) diff --git a/source/lib/allocators/pool.h b/source/lib/allocators/pool.h index 0fea403692..fb7f937045 100644 --- a/source/lib/allocators/pool.h +++ b/source/lib/allocators/pool.h @@ -43,6 +43,7 @@ namespace Allocators { template > class Pool { + NONCOPYABLE(Pool); public: // (must round up because freelist stores pointers inside objects) static const size_t objectSize = ROUND_UP(sizeof(T), sizeof(intptr_t)); diff --git a/source/lib/code_annotation.h b/source/lib/code_annotation.h index 2006eaedfc..26d7529ea7 100644 --- a/source/lib/code_annotation.h +++ b/source/lib/code_annotation.h @@ -30,19 +30,6 @@ #include "lib/sysdep/compiler.h" #include "lib/sysdep/arch.h" // ARCH_AMD64 -/** - * mark a function local variable or parameter as unused and avoid - * the corresponding compiler warning. - * use inside the function body, e.g. void f(int x) { UNUSED2(x); } - **/ -#if ICC_VERSION -// NB: #pragma unused is documented but "unrecognized" when used; -// casting to void isn't sufficient, but the following is: -# define UNUSED2(param) param = param -#else -# define UNUSED2(param) (void)param -#endif - /** * mark a function parameter as unused and avoid * the corresponding compiler warning. @@ -50,6 +37,25 @@ **/ #define UNUSED(param) +/** + * mark a function local variable or parameter as unused and avoid + * the corresponding compiler warning. + * note that UNUSED is not applicable to variable definitions that + * involve initialization, nor is it sufficient in cases where + * an argument is unused only in certain situations. + * example: void f(int x) { ASSERT(x == 0); UNUSED2(x); } + * this asserts in debug builds and avoids warnings in release. + **/ +#if HAVE_C99 && GCC_VERSION // _Pragma from C99, unused from GCC +# define UNUSED2(param) _Pragma("unused " #param) +#elif ICC_VERSION +// ICC 12 still doesn't recognize pragma unused, casting to void +// isn't sufficient, and self-assignment doesn't work for references. +# define UNUSED2(param) do{ if(¶m) {} } while(false) +#else +# define UNUSED2(param) ((void)(param)) +#endif + /** * "unreachable code" helpers diff --git a/source/lib/sysdep/os/win/wsdl.cpp b/source/lib/sysdep/os/win/wsdl.cpp index 318d7bf5d0..f4f66e1bb7 100644 --- a/source/lib/sysdep/os/win/wsdl.cpp +++ b/source/lib/sysdep/os/win/wsdl.cpp @@ -1496,11 +1496,10 @@ static void RedirectStdout() // to prevent the OS from opening a console on startup (ugly). // that means stdout isn't associated with a lowio handle; _close is // called with fd = -1. oh well, there's nothing we can do. - FILE* f = 0; - errno_t ret = _wfreopen_s(&f, OsString(pathname).c_str(), L"wt", stdout); - // (ignore return value - it might indicate 'file already exists' even - // if f is valid, which is what actually counts) - UNUSED2(ret); + FILE* f = 0; + // ignore return value - it might indicate 'file already exists' even + // if f is valid, which is what actually counts. + (void)_wfreopen_s(&f, OsString(pathname).c_str(), L"wt", stdout); if(GetLastError() == ERROR_ALREADY_EXISTS) SetLastError(0); // executable directory (probably Program Files) is read-only for