From -7034096330021023943
X-Google-Language: ENGLISH,ASCII-7-bit
X-Google-Thread: f78e5,fe953dde0d9fda91
X-Google-Attributes: gidf78e5,public
Path: controlnews3.google.com!news2.google.com!newsfeed2.dallas1.level3.net!news.level3.com!newsfeed.mathworks.com!kibo.news.demon.net!mutlu.news.demon.net!demon!mail2news.demon.co.uk!devnull
From: f5xz2bk02@sneakemail.com (Davide Bolcioni)
Newsgroups: comp.std.c++
Subject: Re: n1496
Date: Fri, 28 May 2004 02:05:20 +0000 (UTC)
Organization: TIN
Lines: 220
Approved: fjh@cs.mu.oz.au (Fergus Henderson , moderator of comp.std.c++)
Message-ID: <959io1-hm3.ln1@interbusiness.it>
References: <86vfiuq081.fsf@Zorthluthik.local.bar> <opr79wdvrny9klrv@news.iol.ie> <60c4o1-1e2.ln1@interbusiness.it> <opr8ikyhjey9klrv@news.iol.ie> <1cmco1-u72.ln1@interbusiness.it> <opr8mjkmpgy9klrv@news.iol.ie>
Mime-Version: 1.0
Content-Type: text/plain; charset=us-ascii; format=flowed
Content-Transfer-Encoding: 7bit
X-Trace: mail2news.demon.co.uk 1085709920 14497 10.0.0.1 (28 May 2004 02:05:20 GMT)
X-Complaints-To: abuse@demon.net
NNTP-Posting-Date: Fri, 28 May 2004 02:05:20 +0000 (UTC)
X-Received: from mulga.cs.mu.oz.au ([128.250.1.22])
	by news.demon.co.uk with esmtp (Exim 4.12)
	id 1BTWkJ-0003lg-00
	for mail2news@news.news.demon.net; Fri, 28 May 2004 02:05:20 +0000
X-Received: from mulga.cs.mu.OZ.AU (localhost [127.0.0.1]) by mulga.cs.mu.OZ.AU with ESMTP
	id i4S25HL0013855; Fri, 28 May 2004 12:05:17 +1000 (EST)
X-Received: (from fjh@localhost)
	by mulga.cs.mu.OZ.AU (8.12.10+Sun/8.12.9/Submit) id i4S25GVS013845;
	Fri, 28 May 2004 12:05:16 +1000 (EST)
X-Authentication-Warning: mulga.cs.mu.OZ.AU: fjh set sender to devnull@stump.algebra.com using -f
X-Path: comp-std-cpp-robomod!not-for-mail
X-Robomod: STUMP, ichudov@algebra.com (Igor Chudov)
X-Delivered-To: std-c++@ucar.edu
X-User-Agent: Mozilla/5.0 (X11; U; Linux i686; it-IT; rv:1.4.1) Gecko/20031114
X-Accept-Language: it, en
X-Newsgroups: comp.std.c++
X-NNTP-Posting-Date: Fri, 28 May 2004 01:12:23 MET DST
X-Spamscanner: mailbox5.ucsd.edu  (v1.4 May 20 2004 13:55:33, 5.4/5.0 2.63)
X-MailScanner: PASSED (v1.2.8 35163 i4RNCcuo045139 mailbox5.ucsd.edu)
X-Spam-Checker-Version: SpamAssassin 2.60-mulga_r1 (1.212-2003-09-23-exp) on 
	mulga.cs.mu.OZ.AU
X-Spam-Status: No, hits=-0.0 required=5.2 tests=BAYES_00,FROM_ENDS_IN_NUMS,
	FROM_HAS_MIXED_NUMS,FROM_HAS_MIXED_NUMS3 autolearn=no 
	version=2.60-mulga_r1
Xref: controlnews3.google.com comp.std.c++:541

Niall Douglas wrote:
> On Wed, 26 May 2004 02:46:35 +0000 (UTC), Davide Bolcioni 
> <6805b3x001@sneakemail.com> wrote:

>> in other words, "gcc -c" might
>> produce an "unfinished" object file where this choice of access is
>> deferred, to be resolved when "gcc" is invoked for the final link step
>> just before handling .o files to the linker (nobody said you have to
>> give the linker exactly the same .o files you started with). Since the
>> decisions in this step are C++ specific, it is the compiler's job,
>> not the linker's.
> 
> Not exactly. How ELF does shared libraries means that the app can load a 
> shared library and symbols from that can overwrite symbols currently 
> defined eg; printf() calls one implementation before and then calls a 
> different one thereafter.

This seems to me a violation of the One Definition Rule of C++, so I
should think that: a) the compiler should not produce code causing such
to occur; b) if the programmer causes this to occur within the Makefile,
he had better know what he's doing; c) overwriting symbols is however
useful at times.

> This requires the compiler to always have at 
> least the equivalent overhead of a virtual function call. Even with WPO 
> you can't elide this - to do so breaks things unless you assume no new 
> libraries will be loaded.

Supporting (c) indeed seems to require double indirection; however, I
recollect investigations from KDE people about C++ dynamic linking in
Linux showing that relocations, not indirection, were the main source
of overhead and suggesting prelinking as a solution.

If a member function is already virtual, this is a non issue unless the
implementation doubly indirects (I have not investigated this); if not,
then we have a performance problem if the function is not inline, yet
small enough that the overhead of the virtual call is significant, and
called often. I have seen it happen, although not in recent years, but
not very often (mostly constructors).

> Note that for every symbol which is available outside its DSO, a 
> particularly expensive form of relocation must also be performed at load 
> time which on all implementations I know of is quadratic to symbol 
> number. See Ulrich Drepper's "How to write shared libraries".

Will do.

>> In other words, C/C++ programmers already take a visibility decision in
>> the code, using the language-provided means which the underlying
>> implementation is required to support.
> 
> This is not true for the 
> contents of unnamed namespaces - they merely add extra mangling to the 
> symbol which actually makes the problem worse (longer load & linking 
> times and more code bloat). Why don't unnamed namespaces hide their 
> contents? Because "export" causes searching of unnamed namespaces 
> outside its compiland!

I have not investigated the ramifications of "export" enough to comment
on this; more to come in the future.

>>> I also feel that whether something is visible outside its DSO/DLL is 
>>> part of its API spec and thus interface contract. If you disagree 
>>> with this, consider how public/protected/private relate to class 
>>> design and note that similar logic applies to both.
>>
>> It seems to me that you are unwilling to abstract from the concrete
>> implementation; if what you're after is a further layer of 
>> modularization, you might want to research "module" concepts such as
>> those found in Modula languages or the "package" concept of Java.

If I write that a member function is private, I mean exactly that; it
cannot be called from outside the class. The mangled symbol for its
implementation should not require double indirection to reach, once
WPO coalesces invocations from separate .o files; if the programmer
puts some implementations in a .so and some in another, double
indirection would be required and a comment in the standard should
warn of the associated performance cost. Most programmers would
not do that.

The above, however, still allows the programmer to overwrite symbols
through linker directives, or even by making the "mistake" of putting
the implementations he wants to override in a separate .so, causing
the compiler to use double indirection and all that.

If I write that said member function is protected, I am making an
entirely different statement: any member function of a derived class
can invoke it. The set of callers is open-ended and might include
plugins accessed with dlopen(); if the symbol is not visible, a
plugin could be written which is legal C++, compiles, but fails at
dlopen() time (this can happen today with some doctoring of the ELF
binary, unless I'm mistaken, but is clearly a bug).

The C++ language, by itself, does not allow you to directly restrict
the set of classes derived from a base class, although posting the
problem on comp.lang.c++.moderated might turn out a clever workaround;
if such a feature were necessary and introduced, I would certainly want
the error to occur at compile time, rather at the customer's site, and
be "your derived class is not on the list of classes allowed to derive", 
not "symbol not found".

If I write public I mean public - anybody can call a public function
from anywhere, which is essentially analogous to the protected case
from the point of view of linking.

> I view DLLs/DSOs as as fundamental mechanism of compartmentalising code 
> as classes.

This is my point: they are the mechanism, the implementation, while the
C++ language is the interface. The implementation must keep the promises
made in the interface, which the ELF linker does at the price of
substantial contortions; you're suggesting that the interface, the C++
language, be modified to allow faster linking; I'm objecting that your
suggested change to the interface makes for a poor interface (actually
this is an objection to n1496, as said previously, which introduces
"piecemeal modularization" irrespective of the default chosen).

>> a syntactic construct to address it on a symbol by symbol
>> basis is inappropriate.

My key objection is to "on a symbol by symbol basis", which is a critique
of n1496; the choice of "default hidden" would exacerbate the problem.

> Also I like how right now things can be subdivided 
> one way at the source level (via namespaces) but a totally different way 
> at binary level - to me, this ADDS value through intuitiveness.

I both agree and disagree; I agree that some latitude in the organization
of code at binary level is highly desiderable, but only as long as this 
does not break the contract established by the C++ language.

> If you could show me more proposed syntax, I could say a lot more. While 
> I'm initially negative, I could be very easily swayed as TBH I don't 
> have enough experience of what you propose would mean.

Let's assume that the intent is to get rid of double indirection; it 
seems to me that to achieve this you have to know, at WPO time, that
all references to a symbol in the program will use the definition from
the program itself; indirection will still be needed for accessing said
definition from shared objects and for accessing symbols referenced but
not defined in the program. You want to say "this definition cannot be
overridden" for proteced/public member functions, and for namespace
scope symbols.

One syntax to achieve this might be inspired from Java:

   #include "sample_class.h" // Declaration.

   package main_program; // Not a scoping construct.

   class sample_class { ... } // Definition.
   void f(const sample_class& arg) { ... } // Definition.

The implementation would label the symbols as belonging to a package
named "main_program" - this is the reason for having

   package main_program;

rather than

   package main_program { ... }

which might suggest that you can have multiple packages in the
same source file (on second thought, this might not be such a
bad idea). The package where main() appears would become the
executable program after linking; other packages would become
shared objects (actually shared objects candidates).

Symbols defined in a package are not available outside the
defining package unless explicitly imported

   #include "sample_class.h" // Declaration.
   package shared_object;
   import class sample_class from main_program;

and

   #include "sample_class.h" // Declaration.
   package plugin;
   import class sample_class from main_program;
   import void f(const sample_class& arg) from main_program;

Please note that I say "not available" as I do not wish to suggest
further complications of C++ visibility rules; a symbol which is not
visible cannot be imported.

Importing a symbol states the intent to reference the existing
definition and allows the compiler to report a conflicting definition
as an error straight away. Importing a symbol which is already defined
is likewise immediately reported as an error.

Allowing multiple definitions of the same symbol in separate packages
would cause a violation of the ODR rule, but only if said packages
are ever collected together as a C++ program.

When the definition of a symbol is encountered but the symbol is not
imported, the compiler is allowed to assume that this is the definition
referenced throughout the package, an assumption it can exploit at WPO
time; a jump table would still be necessary, since other shared objects
might reference the definition.

When prelinking, conflicting definitions of the same symbol would be
detected and would cause a violation of the ODR; the same would happen
if a plugin attempted to redefine a defined symbol upon dlopen().

All things considered, the above seems a little too much for saving one
indirection from nonvirtual functions; maybe the module/package concept
can bring other benefits from C++, however.

Cheers,
Davide Bolcioni
-- 
Paranoia is a survival asset.

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]



