Console.h
Code: Select all
class Console
{
protected:
void putchar(char c) = 0; // Architecture dependent putchar function, must be implemented by each console.
public:
void WriteFormat(const char* format, ...); // Similar to printf.
};
// Location where the Console object will be placed in memory.
extern char console_space[];
// Returns a reference to the Console object.
inline Console& console(void) { return(reinterpret_cast<Console&>(console_space)); }
Code: Select all
#include <Console.h>
void Console::WriteFormat(const char* format, ...)
{
// Find out which characters to print and call putchar() to put them on the screen.
}
Code: Select all
#include <Console.h>
class VGAConsole : public Console
{
private:
char cursor_x, cursor_y;
protected:
void putchar(char c);
};
Code: Select all
#include <arch/x86/VGAConsole.h>
void VGAConsole::putchar(char c)
{
// Put character on the screen
}
char console_space[sizeof(VGAConsole)];
Code: Select all
#include <arch/x86/VGAConsole.h>
void Init(void)
{
// Use placement new to create Console object at reserved space.
new (console_space) VGAConsole();
// Write something.
console().WriteFormat("Console started!\n");
}
- It is easily portable. To implement a new console type, one simply needs to derive a new class from Console and implement putchar (and other architecture dependent functions which I omitted in my code example). It can simply be used through the console() wrapper function.
- There is no need to store a pointer to the console object. The compiler transforms the inlined console() function to a reference to console_space, and the linker inserts the correct address.
- Whenever a console function is called, the location of the console_space is passed as an argument - even though this is a constant value, i.e. it is the same for every call since there is only one instance of the Console class in the kernel.
- Every access to member variables of the console object is indirected through the "this" pointer - which always points to the same, unique Console instance.
- Every call to an architecture dependent console function is indirected through the vtable of the corresponding architecture dependent derived class. Again, this is unnecessary, since exactly one implementation of every function such as putchar is compiled into the kernel.
- GCC's "strict aliasing" rules are broken since an object of type char[] is referenced through a pointer of type Console&.