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,FREEMAIL_FROM, T_FILL_THIS_FORM_SHORT autolearn=unavailable autolearn_force=no version=3.4.4 X-Received: by 2002:a02:1bd3:: with SMTP id 80-v6mr9722113jas.23.1532495764622; Tue, 24 Jul 2018 22:16:04 -0700 (PDT) X-Received: by 2002:aca:75c9:: with SMTP id q192-v6mr61137oic.3.1532495764487; Tue, 24 Jul 2018 22:16:04 -0700 (PDT) Path: eternal-september.org!reader01.eternal-september.org!reader02.eternal-september.org!feeder.eternal-september.org!xmission!news.snarked.org!border2.nntp.dca1.giganews.com!nntp.giganews.com!g2-v6no1593838itf.0!news-out.google.com!k71-v6ni1959itk.0!nntp.google.com!g2-v6no1593835itf.0!postnews.google.com!glegroupsg2000goo.googlegroups.com!not-for-mail Newsgroups: comp.lang.ada Date: Tue, 24 Jul 2018 22:16:04 -0700 (PDT) In-Reply-To: Complaints-To: groups-abuse@google.com Injection-Info: glegroupsg2000goo.googlegroups.com; posting-host=50.66.161.135; posting-account=lzqe5AoAAADHhp_gregSufVhvwu22fBS NNTP-Posting-Host: 50.66.161.135 References: <1c73f159-eae4-4ae7-a348-03964b007197@googlegroups.com> <878t9nemrl.fsf@nightsong.com> <62df3c25-057c-4cc5-a899-b91413613b83@googlegroups.com> <7306c5a4-7810-4e5d-9896-124b9841832b@googlegroups.com> User-Agent: G2/1.0 MIME-Version: 1.0 Message-ID: Subject: =?UTF-8?B?UmU6IEhvdyB0byBnZXQgQWRhIHRvIOKAnGNyb3NzIHRoZSBjaGFzbeKAnT8=?= From: Brad Moore Injection-Date: Wed, 25 Jul 2018 05:16:04 +0000 Content-Type: text/plain; charset="UTF-8" Xref: reader02.eternal-september.org comp.lang.ada:53955 Date: 2018-07-24T22:16:04-07:00 List-Id: On Saturday, July 14, 2018 at 9:48:59 AM UTC-6, Niklas Holsti wrote: > On 18-07-14 17:28 , Shark8 wrote: > > On Saturday, July 14, 2018 at 4:07:16 AM UTC-6, Dmitry A. Kazakov wrote: > >> > >> I doubt there is any real problem in Ada that cannot be resolved keeping > >> *everything* backward compatible. > > > > There are some things that can't be fixed while keeping backwards > > compatibility and *NOT* adding yet-another-way-to-do-this; which > > is what C++ did with it's myriad of pointers and references. > > > > A couple of good examples: > [snip] > > * Protected objects (What's in the private section ought to be the body, IMO.) > > protected type Signal_Object is > > entry Wait; > > procedure Signal; > > function Is_Open return Boolean; > > private > > Open : Boolean := False; -- WHY ARE WE EXPOSING THIS? > > end Signal_Object; > > The answer to your shouted question is (as I suspect you know): because > a protected type declaration defines a type that will be used to declare > objects, and the compiler must know the size, structure and alignment of > the data contained in the object before it can make code to create such > an object. > > If the private component declarations were moved to the body, clients > of the package that defines the protected type would come to depend on > the body of that package. > > Nevertheless, as such a dependency is usually not fatal (resulting also > from generics) I don't see why Ada could not be extended to allow the > private component declarations to be optionally postponed to the body, > for example with this declaration syntax (just a what-came-first-to-mind > sketch): > > protected type Signal_Object is > entry Wait; > procedure Signal; > function Is_Open return Boolean; > private in body; -- NOT current Ada! > end Signal_Object; > > and this body syntax (the declarations of the object components come > first, because the operations must see them): > > protected body Signal_Object is > Open : Boolean := False; -- NOT current Ada! > entry Wait > ... -- Body of Wait. > ... -- Bodies of Signal and Is_Open. > end Signal_Object; > > I don't see any backward compatibility problem with this. > > Of course it is "yet another way" to declare the components of a > protected type. So what? If you convince enough people that this kind of > protected declaration is desirable, you might be able to convince the > ARG to add it to Ada. Well, I cant speak for others, but I am so far not convinced that this kind of protected declaration is desirable. I think it can be done without breaking backward > compatibility with current Ada. I think what you are asking for is too close to what is already available, and so I think there is not enough benefit to add "more ways to doing the same thing" Here are two ways to do something similar. First, we could use an incomplete type (Taft amendment type) to move the protected type declaration to the body of a package, as in... package Q is type Signal_Object is limited private; procedure Wait (Item : in out Signal_Object); -- with Nonblocking => False; procedure Signal (Item : in out Signal_Object); -- with Nonblocking; function Is_Open (Item : Signal_Object) return Boolean; -- with Nonblocking; function Create return Signal_Object; private type Private_In_Body; type Signal_Object is not null access Private_In_Body; end Q; package body Q is protected type Private_In_Body is entry Wait; procedure Signal; function Is_Open return Boolean; private Open : Boolean := False; end Private_In_Body; protected body Private_In_Body is function Is_Open return Boolean is begin return Open; end Is_Open; procedure Signal is begin Open := True; end Signal; entry Wait when Open is begin null; end Wait; end Private_In_Body; function Create return Signal_Object is begin return new Private_In_Body; end Create; procedure Signal (Item : in out Signal_Object) is begin Item.Signal; end Signal; function Is_Open (Item : Signal_Object) return Boolean is (Item.Is_Open); procedure Wait (Item : in out Signal_Object) is begin Item.Wait; end Wait; end Q; We are hiding the implementation behind an access type, but that is not exposed in the public part of the package, so that seems OK to me. The public view is not of a protected type, but instead a limited type, however with Ada 202x, we will be able to specify that the Wait call is a call that can block (via the Nonblocking aspect), which gives more of a clue about the implementation. I think a reasonable approach however is to have the protected type declared in the private part of the package. Here is one way to do that using protected interfaces.... package P is type Signal_Interface is protected interface; procedure Wait (Item : in out Signal_Interface) is abstract; procedure Signal (Item : in out Signal_Interface) is abstract; function Is_Open (Item : Signal_Interface) return Boolean is abstract; end P; with P; package R is type Signal_Object is synchronized new P.Signal_Interface with private; overriding procedure Wait (Item : in out Signal_Object) with Synchronization => By_Entry; overriding procedure Signal (Item : in out Signal_Object) with Synchronization => By_Protected_Procedure; overriding function Is_Open (Item : Signal_Object) return Boolean; private protected type Signal_Object is new P.Signal_Interface with entry Wait_For_Signal; procedure Set_Signal; function Signal_Is_Open return Boolean; private Open : Boolean := False; end Signal_Object; end R; package body R is protected body Signal_Object is procedure Set_Signal is begin Open := True; end Set_Signal; function Signal_Is_Open return Boolean is begin return Open; end Signal_Is_Open; entry Wait_For_Signal when Open is begin null; end Wait_For_Signal; end Signal_Object; overriding function Is_Open (Item : Signal_Object) return Boolean is begin return Item.Signal_Is_Open; end Is_Open; overriding procedure Signal (Item : in out Signal_Object) is begin Item.Set_Signal; end Signal; overriding procedure Wait (Item : in out Signal_Object) is begin Item.Wait_For_Signal; end Wait; end R; with Ada.Text_IO; use Ada.Text_IO; with Q; with R; procedure Main is begin -- Main Example_1 : declare The_Signal : Q.Signal_Object := Q.Create; task T; task body T is begin delay 5.0; Put_Line ("Signalling..."); Q.Signal (The_Signal); end T; begin Put_Line ("The Signal is " & (if Q.Is_Open (The_Signal) then "Open" else "False")); Put_Line ("Waiting..."); Q.Wait (The_Signal); Put_Line ("Done"); end Example_1; Example_2 : declare The_Signal : R.Signal_Object; task T; task body T is begin delay 5.0; Put_Line ("Signalling..."); The_Signal.Signal; -- Dot_Prefix notation end T; begin Put_Line ("The Signal is " & (if The_Signal.Is_Open then "Open" else "False")); Put_Line ("Waiting..."); The_Signal.Wait; Put_Line ("Done"); end Example_2; end Main; The advantage of this second example, is that the client of the package is more aware that the type, Signal_Object, is a protected object. Also, because it is a tagged type, the dot prefix notation can be used when making the calls, as shown in Example_2. Alternatively, we could have not used interfaces, but declared the protected type in the private part, while using a limited type in the public part as the partial view of the type. Other variants are also possible, such as using a controlled type to provide finalization for types involving heap allocation, etc. Brad Moore > > -- > Niklas Holsti > Tidorum Ltd > niklas holsti tidorum fi > . @ .