Does Ada have this keyword?

In particular, is there a way for the task to get a link to itself?

For instance:

task type someTask; type someTaskAccessor is access someTask; task body someTask is pointerToTask : someTaskAccessor; begin pointerToTask = this; end someTask; 
+3
source share
5 answers

the most obvious solution I could offer is to declare rendez-vous (record) at the very beginning of your task, to which you pass a link to the task just created. another possibility uses the discriminant for your type of task, the role of which is to indicate the new task where it is (pass access to the new task to the discriminant). Unfortunately, I do not have an Ada compiler, so I cannot give you any working example.

in any case, based on your comment: you need to create a new task somewhere, and you will also need to determine where this new task will go into your doubly linked list (you need to know at least one existing task when creating a new one, so that they can communicate: they will not find themselves magically). You can take advantage of this moment when you have a newly created task, its left and right peers, to tell everyone who their neighbor is (using rendez-vous again).

+4
source

The Ada.Task_Identification package provides the Current_Task function to retrieve the current Task_ID task.

+4
source

A few things here.

First, Ada does OO differently than C ++. There are no "this" pointers in the language. Sending is performed from the parameters. One consequence of this is that, unlike C ++, you can send more than one parameter. This is another discussion at another time. If you do not like this, you can always specify your send parameter "this".

Secondly, OO concepts are not really well applied to concurrency objects, such as tasks. This is not Ada's mistake. This is a well known issue. Unfortunately, it was rather unimaginably called the "Concurrency Problem", so links to it are linked to programming problems when searching on Google. The main point is that you can do object inheritance and dynamic dispatching, and all these are good things, or you can make them support concurrency. Execution as in the same language structure is very difficult.

In practical terms, if you need a pointer to your own task, you can either make it global, or complete the task that it passes by passing the pointer when using some kind of randomization initialization. I have seen this before in order to complete a task in the work task stack when it ends.

+1
source

Despite the fact that this topic is old, I stumbled upon it, looking for something similar to myself (my need allowed the task to transfer the handle to a secure hash map storage area, to which all tasks have access, affects registration).

You can do this in Ada 2005, believing that this is not recommended, since it disables access checks, but this is the only way I found the task to generate (or find) my own descriptor to pass to the callback functions (note this does not prevent the transfer Task_ID to check for Termination or Is_Callable):

 task type someTask; type someTaskAccessor is access someTask; task body someTask is -- Initialize the access type variable as pointing to the same task it declared in. pointerToTask : someTaskAccessor := someTask'Unchecked_Access; --equiv to "this" ptr begin -- pointerToTask = this; --this is unneeded, pointerToTask is already set! end someTask; 
+1
source

I would reorganize your code if I were you. So, there are some tasks that interact with other tasks, now with two tasks. And there is a linked list that is responsible for saving tasks and managing the insertion / deletion of tasks. This is a global object that synchronized should handle.

That is why I advise you to create a protected object and save a list of tasks in it. Protected is usually used for passive objects, where some resource must be processed synchronously. You may have procedures such as insertion, deletion, etc. This ensures that only one creation and deletion will be performed at a time, and that the linked list will not be inconsistent.

Each task should know the tasks of the "partner", which may change when you insert or delete a task. I advise creating an entry in the task that will update its neighbors. When tasks come or go, the protected object will update its neighbors.

In this case, there is no need to refer to the "this" pointer, since the protected object organizes everything. Only an identifier is required that can identify the task (for deletion).

I am trying to write code, but now I do not have a compiler:

 task type computer; type computer_ptr is access all computer; task type computer is entry init(id:integer); entry set_neighbor(left,right:computer_ptr); end computer; protected comp_list is procedure insert; -- called by organizer procedure remove(from:integer); -- called by task private type comp_list is array(integer range<>) of computer_ptr; comps:comp_list(1..MAX):=(others=>null); -- or use own structure end comp_list; task body computer is id_:integer; left_n,right_n:computer_ptr:=null; begin accept init(id:integer) do id_:=id; end init; while true loop select accept set_neighbor(left,right:computer_ptr) do left_n:=left;right_n:=right; end set_neighbor; or -- do its work end select; if (some_condition) then comp_list.remove(id_); break; end if; end loop; end task computer; protected body comp_list is procedure insert is p:computer_ptr; begin p:=new computer; -- add to list -> nr; p.all.init(nr); -- call set_neighbor to its left and itself end insert; procedure remove(from: integer) is begin -- remove from list and get its neighbors -- call set_neighbor regarding new ones end remove; end comp_list; 
0
source

Source: https://habr.com/ru/post/1412375/


All Articles