From mboxrd@z Thu Jan 1 00:00:00 1970 X-Spam-Checker-Version: SpamAssassin 3.4.4 (2020-01-24) on polar.synack.me X-Spam-Level: X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00 autolearn=ham autolearn_force=no version=3.4.4 X-Google-Thread: 103376,21960280f1d61e84 X-Google-Attributes: gid103376,public X-Google-Language: ENGLISH,ASCII-7-bit Path: g2news2.google.com!news3.google.com!border1.nntp.dca.giganews.com!nntp.giganews.com!newsfeed00.sul.t-online.de!newsfeed01.sul.t-online.de!t-online.de!solnet.ch!solnet.ch!news-zh.switch.ch!switch.ch!cernne03.cern.ch!not-for-mail From: Maciej Sobczak Newsgroups: comp.lang.ada Subject: Re: How come Ada isn't more popular? Date: Tue, 06 Feb 2007 15:16:08 +0100 Organization: CERN News Message-ID: References: <1169636785.504223.139630@j27g2000cwj.googlegroups.com> <45b8361a_5@news.bluewin.ch> <3pejpgfbki.fsf@hod.lan.m-e-leypold.de> NNTP-Posting-Host: abpc10883.cern.ch Mime-Version: 1.0 Content-Type: text/plain; charset=ISO-8859-1; format=flowed Content-Transfer-Encoding: 7bit X-Trace: cernne03.cern.ch 1170771368 23038 137.138.37.241 (6 Feb 2007 14:16:08 GMT) X-Complaints-To: news@@cern.ch NNTP-Posting-Date: Tue, 6 Feb 2007 14:16:08 +0000 (UTC) User-Agent: Thunderbird 1.5.0.9 (X11/20061220) In-Reply-To: Xref: g2news2.google.com comp.lang.ada:9023 Date: 2007-02-06T15:16:08+01:00 List-Id: Markus E Leypold wrote: >> And I stress again - GC is not the only solution for >> manual memory management. > > OK. I accept that for the moment. I'm just not convinced you can do > everything you need with scope bound memory Sure. But for the sake of discussion completeness, you might wish to throw an example of a situation where scoped lifetime will not make it. >> Determinism in both timing and resource consumption? > > Which brings me back to what I said repeatedly to other people: > > (1) That this determinism is very often not a requirement (outside of > embdedded programming) Java programmer wrote a loop where he opened database cursors, released in the cursor finalizer. All was working like a charm, unless put into production, when in one case the loop had to spin many more times than he ever cared to test. GC did not clean up the abandoned cursor objects fast enough and the number of unnecessarily opened cursors hit the server limit. That was the end of this application. The fix was easy: write explicit close/dispose/dismiss/whatever at the end of the loop, so that effectively there was never more than one open cursor. In fact, this was *manual* resource management. The above would be avoided altogether with scoped lifetime. You are right that determinism is very often not a requirement. It is just the life that very often shows that the initial requirements were not complete. > (2) The determinism is shot anyway by using a heap, not by using > GC. Even better: GC can introduce detereminism in space > consumption by compacting the heap, which naive heaps with manual > MM don't do because of fragementation. There is nothing particular in scoped lifetime that would prohibit compacting heaps and there is nothing particular in GC that guarantees it. It's just the statistics based on popular implementations, not a rule. I can perfectly imagine compacting heaps managed by scoped lifetime. > (3) What is often needed are upper limits not determinism and thos > upper limits can be guaranteed with GC or with an appropriate > collector. This refers to memory consumption only, whereas I clearly stated deterministic *time* as a second (first, actually) goal. >>> My impression was that Ada Controlled storage is actually quite a >>> clean concept compared to C++ storage duration. > >> Clean? It adds tag to the type, which then becomes a controlling type >> in every primitive operation. > >> I got bitten by this recently. Adding a destructor to C++ class >> never has any side effects like this. > > I understand. But the Ada OO way is peculiar, but not unmanagable. OK, I accept the word "peculiar". I only oppose "quite a clean concept" in your previous post. :-) >> Apart from this, the bare existence of *two* base types Controlled and >> Limited_Controlled means that the concepts of controlled and limited >> are not really orthogonal in the sense that adding one of these >> meta-properties affects the interface that is "shared" by the other >> aspect. > > Still. Being able to add a Finalize means you need to have a tagged > type. I see no alternative. You might want to take a look at C++. >>> But both tie allocation to program scope, synchronous with a stack. I >>> insist that is not always desirable: It rules out some architecture, >>> especially those where OO abounds. >> What architecture? > > I already say in another post: That is difficult to show with a toy > system. It only shows in larger systems where you really can't / don't > want to say in any give subsystem module how long a certain peice of > data lives. So none of those can be burdened with deallocating it. OK. What about refcounting with smart pointers? >>> The problem with Controlled, BTW, is that it seems to interact with >>> the rest of the language in such a way that GNAT didn't get it right >>> even after ~10 years of development. Perhaps difficult w/o a formal >>> semantics. > >> You see. > > Yes, I see. But GNAT is also a political problem (see the role of > AdaCore, formerly ACT), so (public) GNAT not getting things right > might well not indicate a problem with reading the Ada standard, but > in the release politics for public version. My hint: There is no > incentive to release a high quality public version GNAT. I get the message. Clear enough. >> In other words, it's very nice that GC doesn't preclude me from doing >> some stuff manually, but that's not enough. > > I'm appalled: You don't want GC, but no, it doesn't do enough for you? Exactly. It's not enough, because it doesn't solve the problem of resource management in a general way. > Of yourse YMMV. but when I have it, it works really well for me. I acknowledge that there might be some applications which are strictly memory-oriented. They are just not the ones I usually write. >>> Apart from that languages >>> with GC often provide nice tricks to tie external ressources to their >>> memory proxy and ditch them when the memory proxy is unreachable >> These "nice tricks" are not so nice. Most of all, they provide no >> guarantee whatsoever, even that they will be invoked at all. > > That's not quite true. Those tricks are building blocks to implement > ressources that are automatically finalized when becoming > unreachable. But it's up to the library author to write a complete > implementation. I don't understand. If the is no guarantee that the finalizer will be *ever* called, then what kind of building block it is? >> A friend of mine spent long evenings recently hunting for database >> connection leaks in a big Java application. That's telling something. > > Well -- so he was naive and should have handled / understood that part > of the system better. Sure. In other words, be prepared that with GC you have to handle/understand some parts of the sytem better. > A friend of mine spent half a month with finding > problems with manual allocation/deallocation and sneaking heap > corruption. Does that prove anything? I don't think so. It does prove that your friend did not benefit from the language that provides scoped lifetime. >>> And BTW - in >>> fcuntional langauges you can do more against ressource leaks, sicne >>> you can "wrap" functions: >>> (with_file "output" (with_file "out_put" copy_data)) >>> It's not always done, but a useful micro pattern. > >> Yes, it basically emulates something that is just natural in those >> languages that provide scope-based lifetime out of the box. > > This is no emulation, but how FP does "scope based". Without the > necessity to add exception handling at the client side or without > having to introduce tagged types / classes. Isn't THAT nice? :-) Same thing with scoped lifetime, as implemented in C++. No need for exception handling (unless handling is actually meaninful), nor for changes in the interface. That's nice, I agree. The difference is that in languages with scoped lifetime the lifetime management is a property of the type (and so applies to all instances), whereas the "FP-trick" above is a property of the use-side. Which one is more robust and less prone to bugs? BTW - please show me an example involving 10 objects of different kinds. :-) >>> But I notice, that >>> "Languages like C provide a more general solution (with regard to >>> accessing memory), which is conceptually not related to any kind of >>> fixed type system and can therefore implement any type and data model" >>> would become a valid argument if I agreed with you. >> Except that it's not the point I'm making. > > No, but the structure of the argument is basically the same. The > analogy should help to show why it is (IMHO) invalid. Ok, but please elaborate on the above first, so I'm sure that it relates to my point. >> Tons of exception handling (and not only - every way to leave a scope >> needs to be guarded, not only by exception) are necessary in those >> languages that rely on GC without providing the above possibility at >> the same time. > > No. I've done the same in Ada w/o controlled objects, but using a > generic procedure. > > procedure mark_data_records is new process_cache_with_lock( Operation => mark_record, ... ); > > begin > mark_data_records(...); > end; > > The client side has no burden with exceaption handling. Could you explain this example a bit? >> I agree for references/pointers in polymorphic >> collections. That's not even close to "almost everywhere" for me, but >> your application domain may differ. > > Yes. it does, abviously. You might not be aware, but code destined for > mere consumers (as opposed to embedded code and code destined as tools > for other developers) has a large amount of GUI code in it. Yes. >>> (b) AFAIR there are restrictions on _where_ I can define controlled >>> types. AFAIR that was a PITA. >> That's a mess. I'm sorry to repeat that. > > Yes. But does C++ do it better? The Ada restrictions AFAIK come from > the necessity of separate linking and compilation (you must be able to > relink w/o looking at the body) and C++ treats that against the > ability to add finalizers everyhwere. I don't understand. Adding a finalizer/destructor to the type that didn't have it before means changes in both specs and the body. Relinking is not enough. -- Maciej Sobczak : http://www.msobczak.com/ Programming : http://www.msobczak.com/prog/