From: Hibou57 (Yannick Duchêne) on 7 Feb 2010 23:30 Hi all out there, Whenever a protected type is declared, all of its specification has to be defined at once and not private stuff can be delay (like "type ... is private" would allow). If this protected type is to hold something which is not to be public, the only way to do as far I'm able to do, is to wrap it in a private type as a record component. package P type A_Type is limited private; -- Must be limited, to be able to hold a limited component. function Value (A : A_Type) return Value_Type; -- Value_Type defined somewhere else. procedure Do_Something (A : in out A_Type); -- Potentially blocking. -- Obviously, there are comments to assert such things, -- but I would prefer it to be formally stated. private protected type B_Type is -- Cannot move it in the public part, due -- to a feature (Set_Value) which must not be public. function Value return Value_Type; -- Accessed via the corresponding method on A_Type. procedue Set_Value (New_Value : in Value_Type); -- The A_Type does not have such a corresponding -- method : we want it to remains private. procedure Do_Something; -- Accessed via the corresponding method on A_Type. -- B_Type being protected, this means this is -- a potentially blocking operation. end B_Type; type A_Type is limited record B : B_Type; end record; end P; Then, implementation of methods on A_Type will then simply pass control to the corresponding ones of its B component. All of this, just to hide something which is not to be part of the public specification. I don't like it, because it does not any more publicly shows that things relies on a protected object. Was this a desired consequence when this part of Ada was designed ? Do someone know a reason ? Is there something I'm doing here I should not do ?
From: Martin on 8 Feb 2010 03:30 On Feb 8, 4:30 am, Hibou57 (Yannick Duchêne) <yannick_duch...(a)yahoo.fr> wrote: > Hi all out there, > > Whenever a protected type is declared, all of its specification has to > be defined at once and not private stuff can be delay (like "type ... > is private" would allow). If this protected type is to hold something > which is not to be public, the only way to do as far I'm able to do, > is to wrap it in a private type as a record component. > > package P > > type A_Type is limited private; > -- Must be limited, to be able to hold a limited component. > > function Value (A : A_Type) return Value_Type; > -- Value_Type defined somewhere else. > > procedure Do_Something (A : in out A_Type); > -- Potentially blocking. > -- Obviously, there are comments to assert such things, > -- but I would prefer it to be formally stated. > > private > > protected type B_Type is > -- Cannot move it in the public part, due > -- to a feature (Set_Value) which must not be public. > function Value return Value_Type; > -- Accessed via the corresponding method on A_Type. > procedue Set_Value (New_Value : in Value_Type); > -- The A_Type does not have such a corresponding > -- method : we want it to remains private. > procedure Do_Something; > -- Accessed via the corresponding method on A_Type. > -- B_Type being protected, this means this is > -- a potentially blocking operation. > end B_Type; > > type A_Type is limited record > B : B_Type; > end record; > > end P; > > Then, implementation of methods on A_Type will then simply pass > control to the corresponding ones of its B component. All of this, > just to hide something which is not to be part of the public > specification. > > I don't like it, because it does not any more publicly shows that > things relies on a protected object. > > Was this a desired consequence when this part of Ada was designed ? > > Do someone know a reason ? > > Is there something I'm doing here I should not do ? This is true of task types too. We take the view that if something was a task/protected or not should be hidden from a user (e.g. we may change the behaviour from being task based/not protected, so we abstract away that information). The associated 'rule' for callers is that they can't assume that calls to any operation don't block - but that's true of calling pretty much any package anyway. I wonder if there is room for "pragma (Not_)Blocking"?...Not just as a visual aid but maybe it could also be used extend the usage of "pragma Detect_Blocking" to wrappers for "foreign languages". Cheers -- Martin
From: Hibou57 (Yannick Duchêne) on 8 Feb 2010 04:11 On 8 fév, 09:30, Martin <martin.do...(a)btopenworld.com> wrote: > This is true of task types too. Indeed > We take the view that if something was a task/protected or not should > be hidden from a user (e.g. we may change the behaviour from being > task based/not protected, so we abstract away that information). Your suggestion seems to confirm a feeling I was expressing in a previous thread : http://groups.google.com/group/comp.lang.ada/browse_thread/thread/385c146dd3112519?hl=fr# (sorry for pure Usenet user, it's a google-newsgroup link) > [...] > Any way, a request made to a task is blocking as long as the task is > not ready to fulfill the request (the rendezvous, which is the Ada > primitive for synchronization). So, from the client point of view, a > method implemented on top of a task is not a different thing than a > method implemented on top of a procedure. > [...] > The associated 'rule' for callers is that they can't assume that calls to > any operation don't block - but that's true of calling pretty much any > package anyway. On one hand, an implementation level detail On the other hand, something which I feel should be part of the interface. I would like to underline : part of the interface , because while I was writing these four words, I though part of the interface... but what about the specification ? Most of time I use the words Interface and Specification as equivalent, but there, I see it's not the same. Blocking, is unlikely to be part of any required specification. In the mean time, None- Blocking, is most likely to be a specification requirement. So : implementation detail or mediumly part of specifications ? > I wonder if there is room for "pragma (Not_)Blocking"?...Not just as a > visual aid but maybe it could also be used extend the usage of "pragma > Detect_Blocking" to wrappers for "foreign languages". This sounds good to me in someway (I mean providing the latter question can be answered), as I was also on my side, thinking about a similar thing : should or should not, Ada, have a keyword or a pragma to tell a particular method is potentially blocking ? In the other thread I've pointed, someone suggested me tasks as record components is most of time not a good idea. But as the only way to hide private features, is to wrap the target item in a private record (possibly tagged by the way) type, I wonder what was the reason of this suggestion to avoid it. Do you have on you side some feedback to give about experiencing with task wrapped in private records ? What may be the shortcomings or traps when using tasks as record components ?
From: Alex R. Mosteo on 8 Feb 2010 05:10 Hibou57 (Yannick Duchêne) wrote: > On 8 fév, 09:30, Martin <martin.do...(a)btopenworld.com> wrote: >> This is true of task types too. > Indeed > >> We take the view that if something was a task/protected or not should >> be hidden from a user (e.g. we may change the behaviour from being >> task based/not protected, so we abstract away that information). > > Your suggestion seems to confirm a feeling I was expressing in a > previous thread : > http://groups.google.com/group/comp.lang.ada/browse_thread/thread/385c146dd3112519?hl=fr# > (sorry for pure Usenet user, it's a google-newsgroup link) > >> [...] >> Any way, a request made to a task is blocking as long as the task is >> not ready to fulfill the request (the rendezvous, which is the Ada >> primitive for synchronization). So, from the client point of view, a >> method implemented on top of a task is not a different thing than a >> method implemented on top of a procedure. >> [...] > > >> The associated 'rule' for callers is that they can't assume that calls to >> any operation don't block - but that's true of calling pretty much any >> package anyway. > On one hand, an implementation level detail > On the other hand, something which I feel should be part of the > interface. > I would like to underline : “ part of the interface ”, because while I > was writing these four words, I though “ part of the interface... but > what about the specification ? ” > > Most of time I use the words Interface and Specification as > equivalent, but there, I see it's not the same. Blocking, is unlikely > to be part of any required specification. In the mean time, None- > Blocking, is most likely to be a specification requirement. > > So : implementation detail or mediumly part of specifications ? > >> I wonder if there is room for "pragma (Not_)Blocking"?...Not just as a >> visual aid but maybe it could also be used extend the usage of "pragma >> Detect_Blocking" to wrappers for "foreign languages". > This sounds good to me in someway (I mean providing the latter > question can be answered), as I was also on my side, thinking about a > similar thing : should or should not, Ada, have a keyword or a pragma > to tell a particular method is potentially blocking ? > > In the other thread I've pointed, someone suggested me tasks as record > components is most of time not a good idea. But as the only way to > hide private features, is to wrap the target item in a private record > (possibly tagged by the way) type, I wonder what was the reason of > this suggestion to avoid it. > > Do you have on you side some feedback to give about experiencing with > task wrapped in private records ? What may be the shortcomings or > traps when using tasks as record components ? I have used tasks as record components in (that I can remember) communication related types. My rule of thumb is that as long as the type lifespan is the whole app lifespan, or the type lifespan is derived from the task lifespan (i.e. end of tasking marks the end of the object, and not the other way around), things don't present any surprises. With the caveat that sjw pointed for dynamic deallocation. I cannot remember any unusual difficulties about it, but I'm only a practitioner so it's possible I'm also missing some theoretic or obscure reason to try to avoid it. Frankly, these non-orthogonalities about regular and protected/tasks types were really nagging me in Ada95 (the dot notation only for these types, for instance, and the visibility of privates that you point to). Now at Ada05, it's the mix of traditional and OO notation caused by interfaces what bugs me. Also, the fact that making a protected version of a regular object involves so much boilerplate code is a regular déjà-vu that pains me in my dreams (;-)), compare it to java where adding the keyword synchronized is enough. (Not that I would want java granularity for synchronized; the bugs I've seen caused by "clever" overoptimization of critical sections...)
From: Dmitry A. Kazakov on 8 Feb 2010 05:20
On Mon, 8 Feb 2010 00:30:12 -0800 (PST), Martin wrote: > This is true of task types too. I don't think so. The task specification does not expose barriers and local variables of its body. But the protected type specification does its private operations and components: package P is protected type T is ... private ... -- Why is it here? Is it C++ or Ada? end T; private ... -- It belongs here! Or better to the package body end P; Obviously to me, the syntax should have been like: type T is protected private; -- or "protected with private" entry Foo (X : in out T); function Bar (X : T) return Boolean; private type T is protected record ... end T; -- I don't like "end record" either. If you write "limited" instead of "protected", you cannot publicly declare entries. (And same for the task types) -- Regards, Dmitry A. Kazakov http://www.dmitry-kazakov.de |