libGimbal 0.1.0
C17-Based Extended Standard Library and Cross-Language Runtime Framework
Loading...
Searching...
No Matches
gimbal_context.hpp
1#ifndef GIMBAL_CONTEXT_HPP
2#define GIMBAL_CONTEXT_HPP
3
5#include "../core/gimbal_api_frame.hpp"
6#include "../types/gimbal_version.hpp"
7#include "../core/gimbal_call_stack.hpp"
8#include "../types/gimbal_exception.hpp"
9#include "../preprocessor/gimbal_memory_resource.hpp"
10#include <iostream>
11
12namespace gimbal {
13
14#define GBL_RESULT_CATCH(code) catch
15 (const Exception& resultException) {
16 code = resultException.getResult(); \
17} catch
18 (...) {
19 code = Result(Result::ErrorUnhandledException); \
20}
21
22#define GBL_CONTEXT_EXT_C_TO_CPP_BEGIN_NO_THROW(pFrame, UdType)
23 GBL_ASSERT(pFrame);
24 GBL_API_BEGIN(pFrame->pContext);
25 UdType* pUd = static_cast<UdType*>(pFrame->pContextUd);
26 GBL_API_VERIFY_POINTER(pUd)
27
28#define GBL_CONTEXT_EXT_C_TO_CPP_BEGIN(pFrame, UdType)
29 gimbal::Result result = GBL_RESULT_SUCCESS;
30 GBL_UNUSED(result);
32 try {
33
34#define GBL_CONTEXT_EXT_C_TO_CPP_END()
35 } GBL_RESULT_CATCH(GBL_API_RESULT());
36 GBL_API_END();
37
38class Context:
39 public GblContext,
41{
42public:
43
44
45 static Context* fromGblObj(GblContext* pContext) {
46 return pContext ?
47 static_cast<Context*>(GblObject_userdata(GBL_OBJECT(pContext)))
48 : NULL;
49 }
50
51 Context(void) {
52
53 pOldClass_ = GBL_CONTEXT_CLASS(GblClass_createFloating(GBL_CONTEXT_TYPE));
54 GblContextClass* pClass = GBL_CONTEXT_CLASS(GblClass_createFloating(GBL_CONTEXT_TYPE));
55
56 pClass->iAllocatorIFace.pFnAlloc = gblMemAlloc_;
57 pClass->iAllocatorIFace.pFnRealloc = gblMemRealloc_;
58 pClass->iAllocatorIFace.pFnFree = gblMemFree_;
59 pClass->iLoggerIFace.pFnWrite = gblLogWrite_;
60 pClass->iLoggerIFace.pFnPush = gblLogPush_;
61 pClass->iLoggerIFace.pFnPop = gblLogPop_;
62
63 Exception::checkThrow(GblInstance_constructWithClass(GBL_INSTANCE(static_cast<GblContext*>(this)), GBL_CLASS(pClass)));
64
65 GblObject_userdataSet(GBL_OBJECT(static_cast<GblContext*>(this)), this);
66
67 }
68
69
70 virtual ~Context(void) {
71 GblInstance_destruct(GBL_INSTANCE(static_cast<GblContext*>(this)));
73 }
74
75
76 static Version getVersion(void) {
77 Version version;
78 //Exception::checkThrow(gblContextVersion(&version, nullptr));
79 return version;
80 }
81
82
83 const CallRecord& getCallRecord(void) const {
84 return *static_cast<const CallRecord*>(&this->lastIssue);
85 }
86
87 void clearCallRecord(void) {
88 Exception::checkThrow(GblContext_lastIssueClear(this));
89 }
90
91
92 // ===== overriding GblContext C API user callbacks =====
93
94 virtual void logPush(const StackFrame& frame) {
95 GBL_API_BEGIN(frame.pContext);
96 GBL_API_CALL(pOldClass_->iLoggerIFace.pFnPush((GblILogger*)static_cast<GblContext*>(this), &frame));
97 GBL_API_END_BLOCK();
98 Exception::checkThrow(GBL_API_RESULT());
99 }
100 virtual void logPop(const StackFrame& frame, uint32_t count) {
101 gimbal::Result result = pOldClass_->iLoggerIFace.pFnPop((GblILogger*)static_cast<GblContext*>(this), &frame, count);
102 Exception::checkThrow(result);
103 }
104 virtual void logWrite(const StackFrame& frame, LogLevel level, const char* pFmt, va_list varArgs) {
105 GBL_API_BEGIN(static_cast<GblContext*>(this));
106 GBL_API_CALL(pOldClass_->iLoggerIFace.pFnWrite((GblILogger*)static_cast<GblContext*>(this), &frame, level, pFmt, varArgs));
107 GBL_API_END_BLOCK();
108 Exception::checkThrow(GBL_API_RESULT());
109 }
110
111 virtual void* memAlloc(const StackFrame& frame, Size size, Size alignment, const char* pDebugInfoStr) {
112 void* pPtr = nullptr;
113 GBL_API_BEGIN(static_cast<GblContext*>(this));
114 GBL_API_CALL(pOldClass_->iAllocatorIFace.pFnAlloc((GblIAllocator*)static_cast<GblContext*>(this), &frame, size, alignment, pDebugInfoStr, &pPtr));
115 GBL_API_END_BLOCK();
116 Exception::checkThrow(GBL_API_RESULT());
117 return pPtr;
118 }
119
120 virtual void* memRealloc(const StackFrame& frame, void* pPtr, Size newSize, Size newAlign) {
121 void* pNewPtr = nullptr;
122 GBL_API_BEGIN(static_cast<GblContext*>(this));
123 GBL_API_CALL(pOldClass_->iAllocatorIFace.pFnRealloc((GblIAllocator*)static_cast<GblContext*>(this), &frame, pPtr, newSize, newAlign, &pNewPtr));
124 GBL_API_END_BLOCK();
125 Exception::checkThrow(GBL_API_RESULT());
126 return pNewPtr;
127 }
128
129 virtual void memFree(const StackFrame& frame, void* pPtr) {
130 GBL_API_BEGIN(static_cast<GblContext*>(this));
131 GBL_API_CALL(pOldClass_->iAllocatorIFace.pFnFree((GblIAllocator*)static_cast<GblContext*>(this), &frame, pPtr));
132 GBL_API_END_BLOCK();
133 Exception::checkThrow(GBL_API_RESULT());
134 }
135
136 //===== overridden from memory_resource =====
137 virtual void* do_allocate(size_t bytes, size_t align) override {
138 GBL_API_BEGIN(static_cast<GblContext*>(this));
139 void* pValue = nullptr;
140 try {
141 pValue = GBL_API_MALLOC(bytes, align, "PMR SHIT!");
142 } GBL_RESULT_CATCH(GBL_API_RESULT());
143 GBL_API_END_BLOCK();
144 return pValue;
145 }
146 virtual void do_deallocate(void* pPtr, size_t bytes, size_t align) override {
147 GBL_UNUSED(bytes); GBL_UNUSED(align);
148 GBL_API_BEGIN(static_cast<GblContext*>(this));
149 try {
150 GBL_API_FREE(pPtr);
151 } GBL_RESULT_CATCH(GBL_API_RESULT());
152 GBL_API_END_BLOCK();
153 }
154 virtual bool do_is_equal(const memory_resource& other) const noexcept override {
155 return this == &other;
156 }
157
158private:
159
160 GblContextClass* pOldClass_ = nullptr;
161
162 static GBL_RESULT gblLogWrite_(GblILogger* pILogger, const GblStackFrame* pFrame, GBL_LOG_LEVEL level, const char* pFmt, va_list varArgs) {
163 GBL_CONTEXT_EXT_C_TO_CPP_BEGIN(pFrame, Context);
164 static_cast<Context*>((GblContext*)pILogger)->logWrite(*static_cast<const StackFrame*>(pFrame),level, pFmt, varArgs);
166 }
167 static GBL_RESULT gblLogPush_(GblILogger* pILogger, const GblStackFrame* pFrame) {
168 GBL_CONTEXT_EXT_C_TO_CPP_BEGIN(pFrame, Context)
169 static_cast<Context*>((GblContext*)pILogger)->logPush(*static_cast<const StackFrame*>(pFrame));
171 }
172
173 static GBL_RESULT gblLogPop_(GblILogger* pILogger, const GblStackFrame* pFrame, uint32_t count) {
174 gimbal::Result result;
175 try {
176 static_cast<Context*>((GblContext*)pILogger)->logPop(*static_cast<const StackFrame*>(pFrame), count);
177 } catch(const Exception& resultException) {
178 result = resultException.getResult();
179 }
180 catch(...) {
181 result = Result(Result::ErrorUnhandledException);
182 }
183 return result;
184 }
185
186 static GBL_RESULT gblMemAlloc_(GblIAllocator* pIAllocator, const GblStackFrame* pFrame, GblSize size, GblSize align, const char* pDebugInfoStr, void** ppPtr) {
187 GBL_CONTEXT_EXT_C_TO_CPP_BEGIN(pFrame, Context)
188 *ppPtr = static_cast<Context*>((GblContext*)pIAllocator)->memAlloc(*static_cast<const StackFrame*>(pFrame), size, align, pDebugInfoStr);
189 GBL_API_VERIFY(*ppPtr, GBL_RESULT_ERROR_MEM_ALLOC);
191 }
192 static GBL_RESULT gblMemRealloc_(GblIAllocator* pIAllocator, const GblStackFrame* pFrame, void* pPtr, GblSize newSize, GblSize newAlign, void** ppNewPtr) {
193 GBL_CONTEXT_EXT_C_TO_CPP_BEGIN(pFrame, Context)
194 *ppNewPtr = static_cast<Context*>((GblContext*)pIAllocator)->memRealloc(*static_cast<const StackFrame*>(pFrame), pPtr, newSize, newAlign);
195 GBL_API_VERIFY(*ppNewPtr, GBL_RESULT_ERROR_MEM_ALLOC);
197 }
198 static GBL_RESULT gblMemFree_(GblIAllocator* pIAllocator, const GblStackFrame* pFrame, void* pPtr) {
199 GBL_CONTEXT_EXT_C_TO_CPP_BEGIN(pFrame, Context)
200 static_cast<Context*>((GblContext*)pIAllocator)->memFree(*static_cast<const StackFrame*>(pFrame), pPtr);
202 }
203
204
205};
206
207
208}
209
210#endif // GIMBAL_CONTEXT_HPP
GBL_RESULT GblClass_destroyFloating(GblClass *pSelf)
Destroys the standalone, "floating" class, releasing its memory allocation.
#define GBL_CLASS(klass)
#define GBL_CONTEXT_CLASS(klass)
#define GBL_CONTEXT_EXT_C_TO_CPP_END()
#define GBL_RESULT_CATCH(code)
#define GBL_CONTEXT_EXT_C_TO_CPP_BEGIN_NO_THROW(pFrame, UdType)
#define GBL_CONTEXT_EXT_C_TO_CPP_BEGIN(pFrame, UdType)
#define GBL_UNUSED(...)
#define GBL_INSTANCE(self)
Casts GblInstance-compatible to GblInstance.
#define GBL_ASSERT(...)
#define GBL_OBJECT(self)
Casts a GblInstance to a GblObject.
#define GBL_RESULT_SUCCESS(value)
#define GBL_CONTEXT_TYPE