From: Alex R. Mosteo on
Hibou57 (Yannick Duchêne) wrote:

> On 8 fév, 11:10, "Alex R. Mosteo" <alejan...(a)mosteo.com> wrote:
>> 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.
> Although I've never confessed it here at comp.lang.ada, I feel the
> same too, at least about notation. Luckily, Ada still allow me to
> preserve consistency granting me the choice to use a dotted notation
> or not : I never use the dotted notation for consistency and clarity
> purpose (except that it's mandatory with protected types and tasks,
> and that's ok for me with record components, as it's implementation
> level).
>
>> 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...)
> I could not tell about comparison between Java and Ada at this point,
> as I've never experienced tasking with Java (I use to self-learn Java,
> but quickly leave it for some reasons). While the point you've spotted
> seems interesting.

My Java is fairly rusty, but if I'm not mistaken, the thing is like this
(corrections welcome!):

(A)
public class Blah { ... } // A regular class

public synchronized class Blah {} // All subprograms of Blah are now
thread-safe.

However, you can also:

(B)
public class Blah
{
public synchronized get() {}
public synchronized set() {}
public bang() {}

}

So basically you choose which methods are synchronized. Or, even further:

(C)
public class Blah
{
public void set() {
synchronized(this) {
// Using this as the lock, operate exclusively within this block.
}
}
}

In my (limited) observing experience, programmers with a tendency to
premature optimization (we all start like that, I fear) avoid (A) because
it's seen as too restrictive. (I don't actually know if Java has a read-only
lock and write lock model like Ada, or using (A) makes all subprograms
mutually exclusive).

So they tend to rely on (B) or (C). At that point, it's really too easy to
somewhere, sometime, forget about a necessary lock, and funny heisenbugs
start to happen caused by obscure race conditions.

I really love the tasking+protected model of Ada.
From: Hibou57 (Yannick Duchêne) on
On 9 fév, 15:47, Robert A Duff <bobd...(a)shell01.TheWorld.com> wrote:
> I agree that it's good to avoid heap management when possible.
> But why can't you declare local variables of type My_Interface'Class,
> initialized with build-in-place function calls?
>
> - Bob

Synchronized-and-the-like interface types are limited, so the built-in-
place is indeed really built-in-place (no kind of conversion allowed
at any stage). The initializer function have to return a class wide
and return it using an extended return statement which is required to
return the same exact type/subtype as the one function returns.

This way of doing thing is not compatible with the implementation-
hiding requirement, as it would require the implementation type to be
exposed in the public part, so that I could define a public function
returning this exact type.
From: Hibou57 (Yannick Duchêne) on
On 9 fév, 20:34, Hibou57 (Yannick Duchêne) <yannick_duch...(a)yahoo.fr>
wrote:
> Synchronized-and-the-like interface types are limited, so the built-in-
> place is indeed really built-in-place (no kind of conversion allowed
> at any stage). The initializer function have to return a class wide
> and return it using an extended return statement which is required to
> return the same exact type/subtype as the one function returns.
>
> This way of doing thing is not compatible with the implementation-
> hiding requirement, as it would require the implementation type to be
> exposed in the public part, so that I could define a public function
> returning this exact type.

I forget to underline : an extension aggregate which would have
otherwise make it possible to initialize a limited class wide type in
an extended return statement, does not work here, as we are to create
a task or protected object (I do not know such a thing as extension
aggregates for Protected and Task).
From: Robert A Duff on
"Hibou57 (Yannick Duch�ne)" <yannick_duchene(a)yahoo.fr> writes:

> Synchronized-and-the-like interface types are limited, so the built-in-
> place is indeed really built-in-place (no kind of conversion allowed
> at any stage). The initializer function have to return a class wide
> and return it using an extended return statement which is required to
> return the same exact type/subtype as the one function returns.
>
> This way of doing thing is not compatible with the implementation-
> hiding requirement, as it would require the implementation type to be
> exposed in the public part, so that I could define a public function
> returning this exact type.

I don't understand the problem. The following should work.
Doesn't it do what you want? Type T exports Public,
but hides Hidden. No heap allocation.

package P is
type T is synchronized interface;
function Create return T'Class;

procedure Public (X : in out T) is abstract;

private

protected type T2 is new T with
overriding entry Public;
entry Hidden;
end T2;

end P;

package body P is
function Create return T'Class is
begin
return Result : T2 do
...
end return;
end Create;

protected body T2 is
entry Public when ... is
begin
...
end Public;

entry Hidden when ... is
begin
...
end Hidden;
end T2;

end P;

with P; use P;
procedure Main is

X : T'Class := Create;

begin
Public (X);
end Main;

- Bob
From: Randy Brukardt on
"Robert A Duff" <bobduff(a)shell01.TheWorld.com> wrote in message
news:wccy6j2mpa0.fsf(a)shell01.TheWorld.com...
> AdaMagica <christoph.grein(a)eurocopter.com> writes:
>
>> OK, but then you have a similar problem to Ada83's syntactically
>> unneeded bodies which Ada95 solved with a pragma.
>
> I think that problem is an illusion. There was a problem,
> but it was a problem with implementations, not with the
> language. How do we know if a given package spec has
> a body? Simple: look on the disk and see if there's
> a source file containing that body. In GNAT, that would
> mean looking for foo.adb.

I think you're forgetting how this happens in practice. And the actual
problem with Ada 83, which was that a unneeded unit with an error had to be
ignored when linking. (The ACVC used to insist on that.) Ada surely needed a
fix to that problem, and it wasn't one with the implementations -- at least
not until they were changed to match the ACVC. (I remember doing that in
Janus/Ada, it was a lot of work and it made things worse for users.
Wonderful.)

Moreover, it is easy to imagine errors that would cause the unit to no
longer be the body (such as misspelling the name, or misspelling "body"), at
which point the implementation would have to guess. But the problem of a
body that the programmer expected to be included being left out would
continue. So while I don't doubt that implementations could have reduced the
problem (in the absense of the ACVC test - the main thing I wanted from Ada
95 was to change the rules enough to repeal that stupid test!), they
couldn't have fixed it completely. Surely the same dynamic would occur for a
separate private part.

I'm also dubious of the basic idea. I suppose you could keep the private
part in a separate file, but I can't imagine any useful way to *compile* it
separately (you'd have to have both parts available in order to do any sort
of code generation). So there wouldn't be much, if any, advantage in terms
of development. (For Janus/Ada, at least, every source file is compiled
separately, and code is generated as necessary without needing anything
other than direct semantic dependencies to have been previously compiled.
That model is impossible for separate private parts; the specification would
not contain enough information to generate any code or any code for calls to
it.)

Randy.