Есть ли в Ada ключевое слово “this”?
Вопрос
В частности, есть ли способ для задачи получить ссылку на саму себя?
Например:
task type someTask;
type someTaskAccessor is access someTask;
task body someTask is
pointerToTask : someTaskAccessor;
begin
pointerToTask = this;
end someTask;
Решение
наиболее очевидное решение, которое я мог бы предложить, - это объявить рандеву (запись) в самом начале вашей задачи, на которую вы передаете ссылку на только что созданную задачу.другая возможность заключается в использовании дискриминанта для вашего типа задачи, роль которого заключается в том, чтобы сообщить новой задаче, где она находится (передать доступ к новой задаче в дискриминант).к сожалению, у меня нет под рукой компилятора Ada, поэтому я не могу привести вам ни одного рабочего примера.
в любом случае, основываясь на вашем комментарии:создание новой задачи должно быть где-то обработано, после чего вам также нужно будет определить, куда эта новая задача попадет в ваш двусвязный список (вам нужно знать хотя бы одну существующую задачу при создании новой, чтобы они могли обмениваться данными:они не обнаружат себя волшебным образом).вы можете воспользоваться этим моментом, когда у вас есть только что созданная задача и ее левые и правые коллеги, чтобы сообщить всем, кто является их соседом (еще раз используя rendez-vous).
Другие советы
Посылка Ada.Идентификация задачи предоставляет функцию Current_Task для извлечения идентификатора текущей задачи Task_ID.
Вот пара вещей.
Во-первых, Ada делает OO иначе, чем C ++.В языке нет указателей "это".Отправка осуществляется вне зависимости от параметров.Одним из следствий этого является то, что можно отключить более одного параметра, в отличие от C ++.Хотя это уже другая дискуссия для другого раза.Если вам это не нравится, вы всегда можете назвать свой параметр диспетчеризации "this".
Во-вторых, концепции OO на самом деле не очень хорошо применимы к объектам параллелизма, таким как задачи.Это не вина Ады.Это хорошо известная проблема.К сожалению, это было довольно невообразимо названо "Проблемой параллелизма", поэтому ссылки на нее в поиске Google завалены проблемами программирования.Основная суть заключается в том, что вы можете заставить объекты поддерживать наследование и динамическую отправку и все такое прочее, или вы можете заставить их поддерживать параллелизм.Сделать и то, и другое в одной и той же языковой структуре очень сложно.
С практической точки зрения, если вам нужен указатель на вашу собственную задачу, вы можете либо сделать его глобальным, либо попросить задачу, которая его выделяет, передать указатель, используя какое-то рандеву инициализации.Я видел, как это делалось раньше, чтобы задача из стека рабочих задач возвращалась в стек "бездействия" по завершении.
Несмотря на то, что эта тема старая, я сам наткнулся на нее в поисках чего-то подобного (мне нужно было разрешить задаче передавать дескриптор самой себе в защищенную область хранения хэш-карты, к которой имеют доступ все задачи, чтобы повлиять на регистрацию).
Вы можете сделать это в Ada 2005, думал, что это не рекомендуется, потому что это отключает проверки доступа, но это единственный способ, который я нашел, чтобы заставить задачу генерировать (или находить) свой собственный дескриптор для передачи в функции обратного вызова (пожалуйста, обратите внимание, что это не исключает передачу Task_ID для проверки завершения или 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's declared in.
pointerToTask : someTaskAccessor := someTask'Unchecked_Access; --equiv to "this" ptr
begin
-- pointerToTask = this; --this is unneeded, pointerToTask is already set!
end someTask;
На вашем месте я бы реорганизовал ваш код.Итак, есть некоторые задачи, которые взаимодействуют с другими задачами, теперь с 2 задачами.И есть связанный список, который отвечает за хранение задач и управляет вставкой / удалением задач.Это глобальный объект, который должен обрабатывать synchronized .
Вот почему я советую вам создать защищенный объект и сохранить список задач внутри него.Защищенный обычно используется для пассивных объектов, где некоторый ресурс должен быть синхронизирован с дескриптором.У вас могут быть такие процедуры, как insert, remove и т.д.Это гарантирует, что одновременно будет выполняться только одно создание и удаление, и связанный список не будет непоследовательным.
Каждая задача должна знать о своих "партнерских" задачах, которые могут измениться при вставке или удалении задачи.Я советую создать запись в задаче, которая будет обновлять своих соседей.Когда задачи приходят или уходят, защищаемый объект обновит соседей.
В этом случае нет необходимости обращаться к указателю "this", потому что защищенный объект все организует.Необходим только идентификатор, который может идентифицировать задачу (для удаления).
Я пытаюсь написать код, но сейчас у меня нет компилятора:
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;