From: Hibou57 (Yannick Duchêne) on
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
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
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
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
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