Page 1 of 1
C++ kernel object structure
Posted: Sun Mar 04, 2012 12:35 pm
by OSwhatever
I wonder how you think is a good way to structure the kernel in the case for C++. Basically what I have now is a bunch of global objects, actually singletons. The singletons are then used in the interface functions. The interface functions are like C functions and they operate on the kernel singletons in order to fulfill the operation. The interface functions are used for both in kernel calls and user calls, often separate functions for kernel and user calls.
The other way to go is to move all object into a class and hosting the objects there. Then you have to move the interface into the class in this case. Basically it becomes like a "kernel class" or "system class". The interface "C functions" cannot be removed though, they will be some kind of wrapper to call the methods in the top class.
What do you think is a good way to structure a kernel?
Re: C++ kernel object structure
Posted: Mon Mar 05, 2012 2:06 am
by Combuster
For things that are truly singleton within the whole range of computers, namespaces are a good bit of syntactic sugar and saves the compiler from having to pass the object all over the place.
That said, C++ is remarkably sensitive to taste and it's not always a good idea to structurally convert things because you found another gimmick.
Re: C++ kernel object structure
Posted: Mon Mar 05, 2012 2:34 am
by Solar
OSwhatever wrote:Basically what I have now is a bunch of global objects, actually singletons.
Singletons, in my humble opinion, are a crutch for Java developers to have global objects (which they wouldn't, otherwise) and still feel good about it (because "it's OO!").
As a C++ developer, make it a global object, make it
obvious it's a global object (e.g. by prefixing "g_" to the variable name), and be done with it.
In an enclosed environment - like a kernel binary - singletons serve no purpose.
The interface functions are like C functions and they operate on the kernel singletons in order to fulfill the operation. The interface functions are used for both in kernel calls and user calls, often separate functions for kernel and user calls.
Either you have a C interface - in which case the functions should be 'extern "C"' - or you have a C++ interface (in which case you should be operating on objects and member functions, not functions handling objects).
Personally, I'd go for C++ interface inside the kernel, and a C interface exported to user space. (C++ is pretty bad for a general-purpose, cross-language interface.) Alternatively, have a C++ interface, with a language-agnostic wrapper.
The other way to go is to move all object into a class and hosting the objects there. Then you have to move the interface into the class in this case. Basically it becomes like a "kernel class" or "system class". The interface "C functions" cannot be removed though, they will be some kind of wrapper to call the methods in the top class.
I'm afraid I cannot follow.
Re: C++ kernel object structure
Posted: Mon Mar 05, 2012 2:51 pm
by gerryg400
Basically what I have now is a bunch of global objects, actually singletons
I'm curious about what sort of objects you have that are global singletons. I have some global variables, perhaps fewer than 10 but they tend to be locks, queues, arrays or similar and aren't singletons. Most of my variables are contained within core- or process- objects.
P.S. I should admit that I'm writing in C and my objects aren't really objects but structs.
Re: C++ kernel object structure
Posted: Tue Mar 06, 2012 11:51 am
by JamesM
gerryg400 wrote:Basically what I have now is a bunch of global objects, actually singletons
I'm curious about what sort of objects you have that are global singletons. I have some global variables, perhaps fewer than 10 but they tend to be locks, queues, arrays or similar and aren't singletons. Most of my variables are contained within core- or process- objects.
P.S. I should admit that I'm writing in C and my objects aren't really objects but structs.
Generally anything ending in "Manager" has the capacity to be a singleton.
Re: C++ kernel object structure
Posted: Tue Mar 06, 2012 1:41 pm
by gerryg400
JamesM wrote:Generally anything ending in "Manager" has the capacity to be a singleton.
Of course. So everything in my timer.c is part of the timer_manager singleton ?
I just don't think like a C++ programmer.
Re: C++ kernel object structure
Posted: Tue Mar 06, 2012 1:46 pm
by Solar
As I said, most C++ developers I know wouldn't bother with the Singleton pattern.
Singleton is for making it impossible to instantiate a second object. In a kernel, you usually have full control about who does what, and you can do without the Singleton pattern (and the additional instructions whenever you go through getInstance()). Besides, C++ provides other ways to keep code from accidentially instantiating a second object.
Re: C++ kernel object structure
Posted: Tue Mar 06, 2012 4:24 pm
by OSwhatever
gerryg400 wrote:Basically what I have now is a bunch of global objects, actually singletons
I'm curious about what sort of objects you have that are global singletons. I have some global variables, perhaps fewer than 10 but they tend to be locks, queues, arrays or similar and aren't singletons. Most of my variables are contained within core- or process- objects.
P.S. I should admit that I'm writing in C and my objects aren't really objects but structs.
As JamesM already pointed I have a bunch of C++ singleton classes that ends with manager. These classes are typically interrupt manager, process manager, named object manager and so on. Basically classes that manage several other objects tends to end up as "managers", something that keeps track of them.
One reason that I forgot to mention is that with singleton you can control when class is supposed to be constructed. You have a singleton template and have the class reside in a byte array. That way it will pass undetected and not end up in ctors. Then you use placement new on the byte array at the time you want to run the constructor.
Re: C++ kernel object structure
Posted: Mon Mar 12, 2012 6:54 am
by brain
Solar wrote:As I said, most C++ developers I know wouldn't bother with the Singleton pattern.
Singleton is for making it impossible to instantiate a second object. In a kernel, you usually have full control about who does what, and you can do without the Singleton pattern (and the additional instructions whenever you go through getInstance()). Besides, C++ provides other ways to keep code from accidentially instantiating a second object.
When ive done anything like this before in c++ i have not forced there to only ever be one instance of the object. This worked well for me, without imposing artificial restictions but was still readable. It was obvious looking at the code that a TimerManager was a factory creating Timer objects, and that you would only ever need one TimerManager even though nothing stopped you making multiple of them.
To be honest, i thought most C++ developers worked this way?
Re: C++ kernel object structure
Posted: Mon Mar 12, 2012 7:34 am
by Solar
brain wrote:When ive done anything like this before in c++ i have not forced there to only ever be one instance of the object. This worked well for me, without imposing artificial restictions but was still readable.
I am not sure I understood this correctly.
A Singleton is where you do something like this:
Code: Select all
Timer foo = TimerManager::getInstance()->getTimer();
The implementation of getinstance() looks something like this:
Code: Select all
TimerManager * TimerManager::m_instance = nullptr;
public TimerManager * TimerManager::getInstance()
{
if ( ! m_instance )
{
m_instance = new TimerManager;
}
return m_instance;
}
The whole
idea of the pattern is to ensure that there is only one instance of TimerManager, ever.
If you don't need a global object at all, you can go with a static function...
Code: Select all
Timer foo = TimerManager::getTimer();
...or, if you
want to have a global object but don't care about whether there's more than one, do just that:
Code: Select all
// file scope
TimerManager g_TimerManager;
// function scope
Timer foo = g_TimerManager.getTimer();
Either way, you save some code, a function call, and some confusing indirection.
To be honest, i thought most C++ developers worked this way?
Most design patterns from the famous book of the same name are aimed at "pure" OO languages, with C++ providing more elegant solutions for them. Unfortunately, the "everything has to be done the OO way" motiv has permeated into C++ land, leading to lots of sub-optimal C++ code in existence.