Live data from Hacker News

Object-oriented design patterns in C and kernel development

oshub.org

211–220 of 224 posts

Re: Object-oriented design patterns in C and kernel development

#211
post #184

Earlier quoted context omitted.

If the kernel were written in C++, it would still be done the way it is done now. C++ does not allow unimplemented member functions and the ADTs currently used do. You can emulate that with multiple inheritance, but it is an inferior way of doing this. As I said, these are NOT vtables. The fact that you and some others keep thinking of them as vtables misleads you into thinking that this can be done using the object…

If the kernel were written in C++, it simply had the incentive to be less creative. Since it isn't it can be. It's just a restriction imposed by C++, not a restriction in the loosely defined paradigm of OOP. > As I said, these are NOT vtables Ok, you just define vtables differently then me. To me a vtable is a table of virtual functions that are used to implement polymorphic behaviour of objects. This applies to thei…

The article author is wrong. It happens. Draw a vent diagram with two partially overlapping circles. You and the author are looking at the overlap and concluding the two are the same. They are not, given the stuff outside the overlap.

As for the one distinction you recognize and think is invalid, that distinction is given by the definition you found. You refuse to obey the definition you yourself quoted to settle matter elsewhere in the thread.

Re: Object-oriented design patterns in C and kernel development

#212
post #205

Earlier quoted context omitted.

> You are the one who posted a definition you found and then claimed that it agreed with you X is Y used in Z. Does that mean X is not Y when it is not used in Z? A knife is a sharp object used to cut meat. How do I call the thing to cut fish? Yes, I see how you can parse the definition your way, I didn't thought about that before introducing it. > since it is an ADT, not anything object oriented Yes, they have large…

The point of a vtable is to implement virtual member functions that support inheritance and polymorphism without changing the base class implementations no matter what the child classes do. If you omit the this pointer, you cannot do inheritance that uses the this pointer in an override without changing the implementation of the parent to add the this pointer back, which would be like a tail wagging a dog. Thus, it i…

> The point of a vtable is to implement virtual member functions that support inheritance and polymorphism without changing the base class implementations no matter what the child classes do

I agree.

> If you omit the this pointer, you cannot do inheritance that uses the this pointer in an override

Yes, but:

> If you omit the this pointer, you cannot do inheritance

You can absolutely do inheritance when the child implementation doesn't need a this pointer. You need the this pointer to read/write values of the instance not to know which types it is.

Let me give you an example:

    class Vehicle {
        virtual unsigned int get_number_of_wheels () = 0;
    };

    class Car: Vehicle;
    class Bicycle: Vehicle;

    unsigned int Car::get_number_of_wheels () { return 4; }
    unsigned int Bicycle::get_number_of_wheels () { return 2; }
This is clearly OOP, there is inheritance, a base class, a vtable introduced by the compiler. C++ will still have a this pointer here for consistency, but absolutely isn't needed here.

This is exactly was is going on with check_flags(). The signature is inherited from a (virtual) base class. Part of that interface contract is that the allowed values are only depended upon the file object's type and not on it's values. You choose the implementation invoked at object construction, if it would need a this pointer, it means that the values returned can change during the lifetime of the object.

    The  following  commands manipulate the flags associated with a file descriptor. [...]
    F_SETFD (int)
              Set the file descriptor flags to the value specified by arg.
Why should the set of allowed flags change over the life time of a file descriptor? That is what the kernel prevents here in it's internal interface by refusing to provide a this pointer to a child implementation.

Re: Object-oriented design patterns in C and kernel development

#213
post #206

Earlier quoted context omitted.

> Implementing static member functions this way would cause undefined behavior, which is a bug. Yes. My point is, that it can't be a static member function, because it's overridden by subclasses.

It cannot be overridden by subclasses without risking undefined behavior because there is no this pointer for it to use.

Yes it can. It simply means the subclass implementation has no access to a this pointer. When would undefined behaviour occur here? When a function tries to use a parameter that does not exist in the function signature, that's a compile time error not UB.

Maybe you think that, because a this pointer is needed for dynamic dispatch? A this pointer exists there, it is just not passed to the implementation.

Re: Object-oriented design patterns in C and kernel development

#214
post #207

Earlier quoted context omitted.

> You don’t implement calls to static member functions by putting them into a vtable Yes, you claimed it is like a static member function, I don't think it can be. > The proper way to implement static functions is through static dispatch Yes, but we are talking about dynamic dispatch here. To quote your earlier comment: > which is most unlike a vtable since static member functions are never in vtables You conclude it…

If you leave out the this pointer, it is the equivalent of putting a function pointer to a global function (or a static member function) into the structure. This is not how OOP works. Omitting the this pointer also breaks inheritance, since hypothetical child classes would not be able to override the definition while using the this pointer. Having to edit the parent class to be able to do that is not how OOP works. T…

> If you leave out the this pointer, it is the equivalent of putting a function pointer to a global function (or a static member function) into the structure.

No it is not. Unless you can show me a virtual overridden static member function.

> since hypothetical child classes would not be able to override the definition while using the this pointer

Yes! That's the entire idea here. The non-hypothetical, but indeed existing, child classes are not able to access the object. This is to prescribe potential behaviour for child implementations.

Re: Object-oriented design patterns in C and kernel development

#215
post #208

Earlier quoted context omitted.

This is one interpretation. The other is that the interface of check_flags() specifies, that any implementation of it is only allowed to differ on the type of the object and not any other property. You already prescribe with the chosen arguments in the superclass on which things the child implementation can depend. Why not also do this with the first argument?

You would typically put the this pointer into the first argument when doing OOP in C. You can put the this pointer in the last argument to have it work too. However, you cannot omit it entirely. That is something that is not OOP. It is an ADT.

So suppose you have it, but never use it. Then why have it you can just remove the first parameter. You can have object methods in C++ too, that don't use the this pointer.

Also why do you care exactly about the order of arguments? The nature of the function doesn't change, it's entirely arbitrary and orthogonal to the paradigm the function implements. Another example is the implementation of the equality operator between objects. In languages with syntactic sugar you typically have (self, other), but if its the true equality operator then the order doesn't matter.

Re: Object-oriented design patterns in C and kernel development

#216
post #209

Earlier quoted context omitted.

If you care about this distinction, yes. However the LWN post describes how both can be used to implement the same behaviour, that their is no defined special implementation.

I have no idea what LWN post you mean. You can make stubs trap by doing a NULL function pointer dereference, but that does not make NULL function pointer dereferences the same as stubs in general.

The LWN post the linked article is a comment to? I thought that's what we are discussing here? There are several paragraphs about exactly this issue.

Re: Object-oriented design patterns in C and kernel development

#217
post #210

Earlier quoted context omitted.

To cite Wikipedia: > Object-oriented programming (OOP) is a programming paradigm based on the object – a software entity that encapsulates data and function(s). An OOP computer program consists of objects that interact with one another. A programming language that provides OOP features is classified as an OOP language [...] You don't disagree, that this kernel pattern is about data abstraction. You probably don't dis…

You can use similar logic to declare English to be an example of Chinese. They both have syllables. They both assemble syllables into words that convey meaning. They both use grammars to form relationships between those words. Thus, they must be the same. It is fallacious logic. Some similarities do not make things the same. Data abstraction is also its own topic that is able to stand independently from OOP. What the…

Sorry no, thus are very different, but of course that's not what you arguing for.

I know ADT and OOP are different concepts, in another answer I wrote what I think the base differences are. But they are related, and in the definitions I am familiar with, ADTs are a base concept for OOP. And OOP can be an implementation for ADTs.

If you don't think the implementations I provide are enough to apply to the kernel, can maybe provide your own definition according to which we can evaluate this, because I feel like we are beating around the bush. But please not something that says this can only be happening in an OOP language, to these I would plainly disagree with, because OOP is a paradigm and not a property of a language.

Re: Object-oriented design patterns in C and kernel development

#218
post #211

Earlier quoted context omitted.

If the kernel were written in C++, it simply had the incentive to be less creative. Since it isn't it can be. It's just a restriction imposed by C++, not a restriction in the loosely defined paradigm of OOP. > As I said, these are NOT vtables Ok, you just define vtables differently then me. To me a vtable is a table of virtual functions that are used to implement polymorphic behaviour of objects. This applies to thei…

The article author is wrong. It happens. Draw a vent diagram with two partially overlapping circles. You and the author are looking at the overlap and concluding the two are the same. They are not, given the stuff outside the overlap. As for the one distinction you recognize and think is invalid, that distinction is given by the definition you found. You refuse to obey the definition you yourself quoted to settle mat…

> As for the one distinction you recognize

It's not the only distinction I recognize, its the distinction you think matters here and that seams to be the basis for our disagreement.

This is the term (vtable, VMT) I got told in lectures to describe this pattern, you have yet not pointed me to a different term that you would recognize to be this, so in lack of a better term I will continue to use this.

As to why I think this distinction does not matter here, is because I perceive the compiler to be a tool that generates code which is controlled by the programmer. Thus the programmer in both cases creates codes with the same paradigm, they only differ in the tools used. We generally don't name things differently depending on which tools are used in the creation, except if they are created with a different intention.

Re: Object-oriented design patterns in C and kernel development

#219
post #2

> The article describes how the Linux kernel, despite being written in C, embraces object-oriented principles by using function pointers in structures to achieve polymorphism. This technique predates object oriented programming. It is called an abstract data type or data abstraction. A key difference between data abstraction and object oriented programming is that you can leave functions unimplemented in your abstrac…

An abstract data type is a software design pattern.

The difference is that design patterns are a technique where you use features not implemented by the compiler or language, and all the checks have to be done by the developer, manually.

Thus, you are doing part of the work of the compiler.

In assembler, a function call is a design pattern.

Re: Object-oriented design patterns in C and kernel development

#220

Hi, I don't know much about this. But it seems to me that the OP is doing it differently than the kernel devs. If you read the article that the OP links, then you get the impression that the vtables contain typed function pointers, while OP uses void pointers. Also the main benefit mentioned in the kernel dev article is that you save memory, by not having multiple function pointers in each structure instance, but ins…

> while OP use void pointers OP doesn't use void pointers, he uses void. He writes about functions having no arguments and returning nothing for the same reason other blog posts name functions foo and bar. > OP uses this vtable as a form of indirection to implement runtime method swapping and polymorphism The kernel uses vtables to implement polymorphism, it doesn't store the vtable in the object to save space. If th…

> If there is no polymorphism, you don't use a vtable at all, that's saving even more space.

Not true. You use a vtable even if there is no polymorphism, in cases where you want to have objects store pointers to their methods (OO interface), but don't want each instance to have pointers to all methods. I was referring to this article, which the OP links in his post https://lwn.net/Articles/444910/

Post reply on HN