Вопрос

В частности, есть ли способ для задачи получить ссылку на саму себя?

Например:

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;
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top