lkml.org 
[lkml]   [2006]   [Apr]   [27]   [last100]   RSS Feed
Views: [more markup]  [less markup]  [headers]  [forward] 
 
Messages in this thread
/
FromRoman Kononov <>
SubjectRe: C++ pushback
DateThu, 27 Apr 2006 00:37:21 -0500
Kyle Moffett wrote:
> On Apr 26, 2006, at 22:05:31, Roman Kononov wrote:
>> Kyle Moffett wrote:
>>> On Apr 26, 2006, at 19:00:52, Roman Kononov wrote:
>>>> Linus Torvalds wrote:
>>>>>  - some of the C features we use may or may not be usable from 
>>>>> C++    (statement expressions?)
>>>>
>>>> Statement expressions are working fine in g++. The main difficulties 
>>>> are:
>>>>    - GCC's structure member initialization extensions are syntax
>>>>      errors in G++: struct foo_t foo={.member=0};
>>>
>>> And that breaks a _massive_ amount of kernel code, including such 
>>> core functionality like SPIN_LOCK_UNLOCKED and a host of others.  
>>> There are all sorts of macros that use member initialization of that 
>>> form.
>>
>> This does not break the code at run time, this breaks the code at 
>> compile time, and should be less painful.
> 
> So breaking 90% of the source code at compile time is ok?  I think not.  
> The kernel relies really _really_ heavily on such structure 
> initializers, and breaking them would effectively break the world as far 
> as the kernel is concerned.

I agree: do not break code, fix it. Make it more robust language-wise.

>>>> G++ compiling heavy C++ is a bit slower than gcc. The g++ front end 
>>>> is reliable enough. Do you have a particular bug in mind?
>>>
>>> A lot of people would consider the "significantly slower" to be a 
>>> major bug.  Many people moaned when the kernel stopped supporting GCC 
>>> 2.x because that compiler was much faster than modern C compilers.  
>>> I've seen up to a 3x slowdown when compiling the same files with g++ 
>>> instead of gcc, and such would be unacceptable to a _lot_ of people 
>>> on this list.
>>
>> I agree, it would be a bad idea to compile the existing C code by 
>> g++.  The good idea is to be able to produce new C++ modules etc.
> 
> No, this is a reason why C++ modules are _not_ a good idea.  If you 
> could write the module in C or C++, but in C++ it compiled 100-200% 
> slower, then you would write it in C.  Why?  A simple matter of numbers:
> 
> Say it takes you 100 hours to write and debug the module in C++, and 140 
> to write and debug it in C.  I estimate that at least 200,000 people 
> would download and compile a single version of the kernel with your 
> module (not an unreasonable estimate).  Note that I'm not even including 
> the people who do repeated regression testing of versions, or people who 
> download and compile multiple versions of the kernel.   If the source 
> file takes an average of 1.0 seconds to compile in C and 2.0 seconds to 
> compile in C++, then:
> 
> (2.0 sec - 1.0 sec) * 200,000 = 200,000 seconds = 55.6 hours
> 140 hours - 100 hours = 40 hours
> 40 hours < 55.6 hours
> 
> So for a single version of the kernel your module, you've already wasted 
> 15.6 hours of time across people using it.  Over time that number is 
> just going to grow, _especially_ if people start writing more and more 
> modules in C++ because they can.  If you want to build C++ in the 
> kernel, write a compiler that does not include all the problematic C++ 
> features that add so much parsing time (overloaded operators, etc).

It is hard take this seriously. For people like me, it is 5 times faster 
to type and debug C++ code. And debug time is 50 times more expensive 
then compile time.

>>>> A lot of C++ features are already supported sanely. You simply need 
>>>> to understand them. Especially templates and type checking.
>>>
>>> First of all, the only way to sanely use templated classes is to 
>>> write them completely inline, which causes massive bloat.  Look at 
>>> the kernel "struct list_head" and show me the "type-safe C++" way to 
>>> do that.  It uses a templated inline class, right?  That templated 
>>> inline class gets duplicated for each different type of object put in 
>>> a linked list, no?  Think about how many linked lists we have in the 
>>> kernel and tell me why that would be a good thing.
>>
>> You mentioned a bad example. The struct list_head has [almost?] all 
>> "members" inlined. If they were not, one could simply make a base 
>> class having [some] members outlined, and which class does not enforce 
>> type safety and is for inheritance only.  The template class would 
>> then inherit the base one enforcing type safety by having inline 
>> members. This technique is well known, trust me. If you need real life 
>> examples, tell me.
> 
> Ok, help me understand here:  Instead of helping using one sensible data 
> structure and generating optimized code for that, the language actively 
> _encourages_ you to duplicate classes and interfaces, providing even 
> _more_ work for the compiler, making the code harder to debug, and 
> probably introducing inefficiencies as well.

The C++ language does not encourage anything like this. Instead it 
actively debugs my code. And it does not produce inefficiencies at run 
time unless I do something stupid.

> If C++ doesn't work 
> properly for a simple and clean example like struct list_head, why 
> should we assume that it's going to work any better for more complicated 
> examples in the rest of the kernel?  Whether or not some arbitrary 
> function is inlined should be totally orthogonal to adding type-checking.

You misunderstood something. The struct list_head is indeed a perfect 
type to be templatized with all members inlined. C++ works properly in 
this case.

>>>> Static constructor issue is trivial.
>>>
>>> How so?  When do you want the static constructors to be run?  There 
>>> are many different major stages of kernel-level initialization; 
>>> picking one is likely to make them useless for other code.
>>
>> For #defines core_initcall() ... late_initcall() I would type 
>> something like this:
>>     class foo_t { foo_t(); ~foo_t(); }
>>     static char foo_storage[sizeof(foo_t)];
>>     static foo_t& foo=*reinterpret_cast<foo_t*>(foo_storage);
>>     static void __init foo_init() { new(foo_storage) foo_t; }
>>     core_initcall(foo_init);
>>
>> This ugly-looking code can be nicely wrapped into a template, which, 
>> depending on the type (foo_t in this case), at compile time, picks the 
>> proper stage for initialization.
> 
> You proved my point.  Static constructors can't work.  You can add silly 
> wrapper initcall functions which create objects in static memory at 
> various times, but the language-defined static constructors are yet 
> another C++ feature that doesn't work by default and has to be hacked 
> around.  C++ gives us no advantage over C here either.

Nothing works by default. I did not say that static constructors are 
advantageous. I said that it is easy for the kernel to make static 
constructors working. Global variables should be deprecated anyway.

> Plus this would 
> break things like static spinlock initialization.  How would you make 
> this work sanely for this static declaration:
> 
> spinlock_t foo_lock = SPIN_LOCK_UNLOCKED;
> 
> Under C that turns into (depending on config options):
> 
> spinlock_t foo_lock = { .value = 0, .owner = NULL, (...) };

I would make it exactly like this:
	#define SPIN_LOCK_UNLOCKED (spinlock_t){0,-1,whatever}
	spinlock_t foo_lock=SPIN_LOCK_UNLOCKED;
This is easy to change. The empty structures look far more painful.
> How could that possibly work in C++ given what you've said?  Anything 
> that breaks code that simple is an automatic nonstarter for the kernel.  
> Also remember that spinlocks are defined preinitialized at the very 
> earliest stages of init.  Of course I probably don't have to say that 
> anything that tries to run a function to iterate over all 
> statically-allocated spinlocks during init would be rejected out of hand.

Apparently this would be rejected. Why would it?

Regards
Roman Kononov

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

\
 
 \ /
  Last update: 2006-04-27 07:39    [from the cache]
©2003-2008