Hi,
I noticed requeue isn’t nearly as powerful as I hoped, since unlike normal entry calls it only accepts names, not random expressions designating an object with the entry.
I wanted this:
entry In_Operation (Result: out Tupple'Class) when True is
begin
requeue with abort Matches(Result).In_Operation;
end In_Operation;
Which would have provided dynamic re-routing. Now I don’t know what to do, but I’m sure it will get ugly. What is the reason of this limitation ?
IIRC, it’s because of the runtime imposition that a dynamic operation would impose. Being static was the least expensive operation, handling most needs.
So, to explain, every TASK has a queue for every entry, these entries are serviced with the accept — requeue is resetting back into the accept’s queue. (Again, IIRC.)
Though I don’t know if you really need a dynamic requeue, as it seems simple enough to ‘bounce’ the data.
Generic
Type Element(<>) is private;
Package Bouncer is
Task Instance is
Entry Input ( Object : in Element );
Entry Output( Object : out Element );
end task;
End Bouncer;
Generic
Function Bouncer.Retrieve return Element;
Function Bouncer.Retrieve return Element is
Begin
Return Result : Element do
Bouncer.Instance.Outpur( Result );
End return;
End Bouncer.Retrieve;
You could also make the TASK you need to requeue from a formal parameter of the Retrieve subprogram and use the subprogram renaming to specify where to put the requeued data, instead of using the function’s return as a vehicle.
Any call requires a name. But the name can be a component, element of an array, dereference etc see ARM 4.1. For example:
task type T is
entry X;
end T;
function Route return access T;
Then
task body T is
begin
loop
select
accept X do
requeue Route.X with abort; -- Dynamically determined entry
end X;
or terminate;
end select;
end loop;
end T;
Here is the Route:
type Index is mod 10;
package Seeds is new Ada.Numerics.Discrete_Random (Index);
State : Seeds.Generator;
A : array (Index) of aliased T;
function Route return access T is
begin
return A (Seeds.Random (State))'Access;
end Route;
Huh ? I don’t quite understand why your example works and not mine.
protected body RealtuppleSpace is
function Matches (T: Tupple'Class) return LockedQueue is
begin
if not The_Map.Contains(T'Tag) then
The_Map.Insert (T'Tag);
end if;
return The_Map.Element(T'Tag);
end Matches;
entry In_Operation (Result: out Tupple'Class) when True is
begin
requeue with abort Matches(Result).In_Operation;
end In_Operation;
end RealtuppleSpace;
type AccessToClass is access Tupple'Class;
package newQueues is new Ada.Containers.Vectors (Positive, AccessToClass);
subtype Queue is newQueues.Vector;
protected type LockedQueue is new TuppleSpace with
overriding
procedure Out_Operation
(T : Tupple'Class);
overriding
entry In_Operation
(Pattern : Tupple'Class;
Result : out Tupple'Class);
overriding
entry RD_Operation
(Pattern : Tupple'Class;
Result : out Tupple'Class);
overriding
procedure Inp_Operation
(Pattern : Tupple'Class;
Result : out Tupple'Class);
overriding
procedure RDP_Operation
(Pattern : Tupple'Class;
Result : out Tupple'Class);
private
PatternQueue: Queue;
end LockedQueue;
type AccessToProtected is access LockedQueue;
function Hash (A: Ada.Tags.Tag) return Ada.Containers.Hash_Type is (Ada.Strings.Hash (Ada.Tags.External_Tag(A)));
package newMaps is new Ada.Containers.Hashed_Maps (Key_Type => Ada.Tags.Tag, Element_type => AccessToProtected, Hash => Hash, Equivalent_Keys => "=");
type MyMapType is new newMaps.Map with null record;
Instead of an array, I have a map indexing patterns (represented by an access to a protected object, since they are limited) by the pattern’s tag. LockedQueue’s job is to find the match or create an entry if the pattern is not present, then requeue the call to the pattern’s entries.
I gave LockedQueue the same interface for the fun but don’t have to, it suffices for a requeue target to have the same profile or no parameters.
MyMapType.Element returns a defined type, like in your case. Why should my function call from a container be semantically different from your array component ? I can’t use an array because I don’t know how many patterns there would be. I wanted it to be general, but I guess givingn it fifty slots should be enough…
Beware, a Pickwickean function here! LockedQueue is a limited type. You declared it as
Semantically you cannot return a protected object. And you did not mean it. You meant a reference to an existing object. That is an access to.
P.S. As I said before, refrain from using suspicious language features. By-reference result /= in-place constructor. Ada does not have the former and mistakenly sugars the latter as a “function,” which is NOT. You mean one but get another.
Can someone explain what the dreaded accessibility checks come to do here ?
I finished my Linda space and it works like a charm. Except when you try to define a new tuple type in the program’s declarative part, which is to say, not in library level.
So I have something like:
procedure Essai is
Space: RealTuppleSpace;
type TestType is new tuppleSpacePackage.Tupple with record
A: String (1..10) := (others => ' ');
B: Integer := -10;
end record;
overriding procedure Copy_Into (A: Tupple'Class; B: out TestType);
begin
Space.Out_Operation (Encode(“je ne sai”, -48));
end Essai;
You can see the details in this repo, but I checked and the value and variables are correct up to the point of inserting into the vector:
procedure Out_Operation (T: Tupple'Class) is
begin
Put_line(T'Image);
PatternQueue.Prepend (new Tupple'Class'(T));
end Out_Operation;
Then I get raised PROGRAM_ERROR : tupplespacepackage-realtupples.adb:87 accessibility check failed
The allocator should create an entire new value, copying T. Why would accessibility matter when I know it sees the variable up to that point !
…Naturally the correct approach is to forgo the whole conversion view and class-wide access types and instead store values stream elements then use the 'Read attribute. It came to me too late. Also implementing non-destructive reading with streams seems well above my skills, I can’t read this at all.
tupplespacepackage-realtupples.adb ,tupplespacepackage-realtupples.ads, essai.adb , tupplespacepackage.ads