Created
December 24, 2015 09:58
-
-
Save uucidl/574d08530deab20b9b51 to your computer and use it in GitHub Desktop.
skeleton in the closet
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
OSX: "clang++ -DOS_OSX -g -std=c++11 -nostdinc++ -nostdlib -framework System | |
-Wall -Wextra skeleton.cpp -o skeleton" | |
*/ | |
// Meta | |
#define DOC(...) // to document a symbol | |
#define URL(...) // reference to a resource | |
// Compiler | |
#define CLANG_ATTRIBUTE(x) __attribute__((x)) | |
#define debugger_break() DOC("invoke debugger") asm("int3") | |
// Word Types | |
using u8 = unsigned char; | |
using s8 = signed char; | |
using u16 = unsigned short; | |
using s16 = signed short; | |
using u32 = unsigned int; | |
using s32 = signed int; | |
using u64 = unsigned long; | |
using s64 = signed long; | |
static_assert(sizeof(u8) == 1, "u8"); | |
static_assert(sizeof(s8) == 1, "s8"); | |
static_assert(sizeof(u16) == 2, "u16"); | |
static_assert(sizeof(s16) == 2, "s16"); | |
static_assert(sizeof(u32) == 4, "u32"); | |
static_assert(sizeof(s32) == 4, "s32"); | |
static_assert(sizeof(u64) == 8, "u64"); | |
static_assert(sizeof(s64) == 8, "s64"); | |
// Concepts | |
#define MODELS(...) | |
#define REQUIRES(...) | |
#define Iterator typename | |
#define Integral typename | |
#define UnaryFunction typename | |
// SizeOf | |
#define SizeOf(x) sizeof(x) | |
// PointerOf | |
#define PointerOf(T) T * | |
// DistanceType | |
template <typename T> struct distance_type_impl { | |
}; | |
template <typename T> struct distance_type_impl<PointerOf(T)> { | |
using type = u64; | |
}; | |
#define DistanceType(T) typename distance_type_impl<T>::type | |
// memory_address | |
using memory_address = PointerOf(u8); | |
static_assert(SizeOf(memory_address) == SizeOf(DistanceType(memory_address)), | |
"DistanceType(memory_address) incorrect for architecture"); | |
// Algorithms | |
template <Integral I> bool zero(I x) { return x == I(0); } | |
template <Integral I> I successor(I x) { return x + 1; } | |
template <Integral I> I predecessor(I x) { return x - 1; } | |
template <typename T> T source(PointerOf(T) x) { return *x; } | |
template <typename T> PointerOf(T) successor(PointerOf(T) x) { return x + 1; } | |
template <typename T> PointerOf(T) predecessor(PointerOf(T) x) { return x - 1; } | |
template <Iterator InputIterator, Integral I, UnaryFunction Op> | |
REQUIRES(Domain(Op) == ValueType(InputIterator)) InputIterator | |
for_each_n(InputIterator first, I n, Op operation) | |
DOC("for `n` times, advance iterator `first` and apply `operation` on its " | |
"source") | |
{ | |
while (!zero(n)) { | |
operation(source(first)); | |
first = successor(first); | |
n = predecessor(n); | |
} | |
return first; | |
} | |
// Os | |
// die if bool is false | |
#define fatal_ifnot(x) \ | |
if (!(x)) { \ | |
debugger_break(); \ | |
fatal(); \ | |
} | |
void fatal() CLANG_ATTRIBUTE(noreturn) | |
DOC("kill the current process and return to the OS"); | |
/// allocate block from the OS' virtual memory | |
memory_address vm_alloc(DistanceType(memory_address) size) | |
DOC("allocate from virtual memory"); | |
/// release a block from the OS' virtual memory | |
void vm_free(DistanceType(memory_address) size, memory_address data) | |
DOC("free from virtual memory"); | |
// Main | |
int main(int argc, char **argv) DOC("application entry point") | |
{ | |
auto memory = vm_alloc(1024 * 1024 * 1024); | |
for_each_n(argv, argc, [](char *arg) { | |
// ... | |
}); | |
vm_free(1024, memory); | |
} | |
// Os | |
#if defined(OS_OSX) | |
#include <unistd.h> // for _exit | |
#include <mach/mach.h> // for vm_allocate | |
void fatal() { _exit(-3); } | |
memory_address vm_alloc(DistanceType(memory_address) size) | |
{ | |
fatal_ifnot(size > 0); | |
vm_address_t address = 0; | |
auto vm_allocate_result = vm_allocate(mach_task_self(), &address, size, true); | |
fatal_ifnot(KERN_SUCCESS == vm_allocate_result); | |
return memory_address(address); | |
} | |
void vm_free(DistanceType(memory_address) size, memory_address address) | |
{ | |
auto vm_deallocate_result = | |
vm_deallocate(mach_task_self(), vm_address_t(address), size); | |
fatal_ifnot(KERN_SUCCESS == vm_deallocate_result); | |
} | |
#else | |
#error "Unimplemented OS module" | |
#endif |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment