| @@ -34,7 +34,7 @@ class Bucket_Allocator { | |||||
| } | } | ||||
| public: | public: | ||||
| Bucket_Allocator(unsigned int bucket_size, unsigned int initial_bucket_count) { | |||||
| void alloc(unsigned int bucket_size, unsigned int initial_bucket_count) { | |||||
| this->free_list.alloc(); | this->free_list.alloc(); | ||||
| this->bucket_size = bucket_size; | this->bucket_size = bucket_size; | ||||
| next_index_in_latest_bucket = 0; | next_index_in_latest_bucket = 0; | ||||
| @@ -45,7 +45,7 @@ public: | |||||
| buckets[0] = (type*)malloc(bucket_size * sizeof(type)); | buckets[0] = (type*)malloc(bucket_size * sizeof(type)); | ||||
| } | } | ||||
| ~Bucket_Allocator() { | |||||
| void dealloc() { | |||||
| for (unsigned int i = 0; i <= next_bucket_index; ++i) { | for (unsigned int i = 0; i <= next_bucket_index; ++i) { | ||||
| free(buckets[i]); | free(buckets[i]); | ||||
| } | } | ||||
| @@ -5,10 +5,10 @@ | |||||
| #include <type_traits> | #include <type_traits> | ||||
| template<typename> | template<typename> | ||||
| struct TransientFunction; // intentionally not defined | |||||
| struct Lambda; // intentionally not defined | |||||
| template<typename R, typename ...Args> | template<typename R, typename ...Args> | ||||
| struct TransientFunction<R(Args...)> | |||||
| struct Lambda<R(Args...)> | |||||
| { | { | ||||
| using Dispatcher = R(*)(void*, Args...); | using Dispatcher = R(*)(void*, Args...); | ||||
| @@ -16,7 +16,7 @@ struct TransientFunction<R(Args...)> | |||||
| // wrapped invokable object | // wrapped invokable object | ||||
| void* m_Target; // A pointer to the invokable object | void* m_Target; // A pointer to the invokable object | ||||
| // Dispatch() is instantiated by the TransientFunction constructor, | |||||
| // Dispatch() is instantiated by the Lambda constructor, | |||||
| // which will store a pointer to the function in m_Dispatcher. | // which will store a pointer to the function in m_Dispatcher. | ||||
| template<typename S> | template<typename S> | ||||
| static R Dispatch(void* target, Args... args) | static R Dispatch(void* target, Args... args) | ||||
| @@ -25,7 +25,7 @@ struct TransientFunction<R(Args...)> | |||||
| } | } | ||||
| template<typename T> | template<typename T> | ||||
| TransientFunction(T&& target) | |||||
| Lambda(T&& target) | |||||
| : m_Dispatcher(&Dispatch<typename std::decay<T>::type>) | : m_Dispatcher(&Dispatch<typename std::decay<T>::type>) | ||||
| , m_Target(&target) | , m_Target(&target) | ||||
| { | { | ||||
| @@ -34,7 +34,7 @@ struct TransientFunction<R(Args...)> | |||||
| // Specialize for reference-to-function, to ensure that a valid pointer is | // Specialize for reference-to-function, to ensure that a valid pointer is | ||||
| // stored. | // stored. | ||||
| using TargetFunctionRef = R(Args...); | using TargetFunctionRef = R(Args...); | ||||
| TransientFunction(TargetFunctionRef target) | |||||
| Lambda(TargetFunctionRef target) | |||||
| : m_Dispatcher(Dispatch<TargetFunctionRef>) | : m_Dispatcher(Dispatch<TargetFunctionRef>) | ||||
| { | { | ||||
| static_assert(sizeof(void*) == sizeof target, | static_assert(sizeof(void*) == sizeof target, | ||||
| @@ -50,18 +50,18 @@ struct TransientFunction<R(Args...)> | |||||
| }; | }; | ||||
| struct Hook : Array_List<TransientFunction<void()>> { | |||||
| struct Hook : Array_List<Lambda<void()>> { | |||||
| Hook() { | Hook() { | ||||
| alloc(); | alloc(); | ||||
| } | } | ||||
| ~Hook () { | ~Hook () { | ||||
| dealloc(); | dealloc(); | ||||
| } | } | ||||
| void operator<<(TransientFunction<void()> f) { | |||||
| void operator<<(Lambda<void()> f) { | |||||
| // FIXME(Felix): Why can I not call Array_List::append here??? Hallo? | // FIXME(Felix): Why can I not call Array_List::append here??? Hallo? | ||||
| if (next_index == length) { | if (next_index == length) { | ||||
| length *= 2; | length *= 2; | ||||
| data = (TransientFunction<void()>*)realloc(data, length * sizeof(TransientFunction<void()>)); | |||||
| data = (Lambda<void()>*)realloc(data, length * sizeof(Lambda<void()>)); | |||||
| } | } | ||||
| data[next_index] = f; | data[next_index] = f; | ||||
| next_index++; | next_index++; | ||||
| @@ -1,23 +1,57 @@ | |||||
| #pragma once | #pragma once | ||||
| #ifdef _PROFILING | #ifdef _PROFILING | ||||
| # include <stdlib.h> | # include <stdlib.h> | ||||
| # include <stdio.h> | # include <stdio.h> | ||||
| # include <string.h> | # include <string.h> | ||||
| # include <time.h> | # include <time.h> | ||||
| // # include <bits/stdc++.h> | |||||
| // # include <iostream> | |||||
| // # include <sys/stat.h> | |||||
| // # include <sys/types.h> | |||||
| #ifdef _MSC_VER | #ifdef _MSC_VER | ||||
| // if windows | |||||
| # include <Windows.h> | |||||
| # include <Windows.h> | |||||
| #else | #else | ||||
| # include <sys/time.h> | |||||
| # include <fcntl.h> | |||||
| # include <sys/stat.h> | |||||
| # include <sys/time.h> | |||||
| # include <sys/time.h> | |||||
| # include <stdint.h> | |||||
| # include <stdbool.h> | |||||
| # include <stddef.h> | |||||
| /* Helpful conversion constants. */ | |||||
| static const unsigned usec_per_sec = 1000000; | |||||
| static const unsigned usec_per_msec = 1000; | |||||
| /* These functions are written to match the win32 | |||||
| signatures and behavior as closely as possible. | |||||
| */ | |||||
| bool QueryPerformanceFrequency(int64_t *frequency) | |||||
| { | |||||
| /* gettimeofday reports to microsecond accuracy. */ | |||||
| *frequency = usec_per_sec; | |||||
| return true; | |||||
| } | |||||
| bool QueryPerformanceCounter(int64_t *performance_count) | |||||
| { | |||||
| struct timeval time; | |||||
| /* Grab the current time. */ | |||||
| gettimeofday(&time, NULL); | |||||
| *performance_count = time.tv_usec + /* Microseconds. */ | |||||
| time.tv_sec * usec_per_sec; /* Seconds. */ | |||||
| return true; | |||||
| } | |||||
| #endif | #endif | ||||
| struct Profiler { | struct Profiler { | ||||
| #ifdef _MSC_VER | |||||
| LARGE_INTEGER tmp_time; | LARGE_INTEGER tmp_time; | ||||
| #else | |||||
| int64_t tmp_time; | |||||
| #endif | |||||
| // same for all threads | // same for all threads | ||||
| inline static char file_template[40] = "\0"; | inline static char file_template[40] = "\0"; | ||||
| @@ -62,22 +96,35 @@ struct Profiler { | |||||
| } | } | ||||
| // initially write the performance frequency | // initially write the performance frequency | ||||
| LARGE_INTEGER pf; | |||||
| QueryPerformanceFrequency(&pf); | |||||
| fprintf(out_file, "%lld,,,,\n", pf.QuadPart); | |||||
| QueryPerformanceFrequency(&tmp_time); | |||||
| #ifdef _MSC_VER | |||||
| fprintf(out_file, "%lld,,,,\n", tmp_time.QuadPart); | |||||
| #else | |||||
| fprintf(out_file, "%ld,,,,\n", tmp_time); | |||||
| #endif | |||||
| is_initialized = true; | is_initialized = true; | ||||
| } | } | ||||
| QueryPerformanceCounter(&tmp_time); | QueryPerformanceCounter(&tmp_time); | ||||
| #ifdef _MSC_VER | |||||
| fprintf(out_file, "->,%lld,%s,%s,%d,%s,%s\n", | fprintf(out_file, "->,%lld,%s,%s,%d,%s,%s\n", | ||||
| tmp_time.QuadPart, name, file, | tmp_time.QuadPart, name, file, | ||||
| line, comment1, comment2); | line, comment1, comment2); | ||||
| #else | |||||
| fprintf(out_file, "->,%ld,%s,%s,%d,%s,%s\n", | |||||
| tmp_time, name, file, | |||||
| line, comment1, comment2); | |||||
| #endif | |||||
| }; | }; | ||||
| ~Profiler() { | ~Profiler() { | ||||
| call_depth -= 1; | call_depth -= 1; | ||||
| QueryPerformanceCounter(&tmp_time); | QueryPerformanceCounter(&tmp_time); | ||||
| #ifdef _MSC_VER | |||||
| fprintf(out_file, "<-,%lld,,,,,\n", tmp_time.QuadPart); | fprintf(out_file, "<-,%lld,,,,,\n", tmp_time.QuadPart); | ||||
| #else | |||||
| fprintf(out_file, "<-,%ld,,,,,\n", tmp_time); | |||||
| #endif | |||||
| if (call_depth == 0) | if (call_depth == 0) | ||||
| fflush(out_file); | fflush(out_file); | ||||
| }; | }; | ||||