Pergunta

Especificamente, há uma maneira para uma tarefa para obter uma referência para si?

Por exemplo:

task type someTask; 
type someTaskAccessor is access someTask;

task body someTask is
    pointerToTask : someTaskAccessor;
begin
    pointerToTask = this;
end someTask;
Foi útil?

Solução

a solução mais evidente que eu poderia sugerir é declarar um rendez-vous (uma entrada), no início de sua tarefa, para a qual você passar uma referência para a tarefa recém-criada. A outra possibilidade é utilizar um discriminante para o seu tipo de tarefa, cujo papel é dizer a uma nova tarefa onde ele está localizado (passe o acesso à nova tarefa para o discriminante). Infelizmente, eu não tenho um compilador Ada na mão para que eu não posso lhe dar qualquer exemplo de trabalho.

De qualquer forma, com base no seu comentário: a criação de uma nova necessidades tarefa a ser tratado em algum lugar, em que ponto você também vai precisar para determinar onde esta nova tarefa vai entrar em sua lista duplamente vinculada (você precisa saber pelo menos uma tarefa existente ao criar um novo para que eles se comuniquem: eles não vão descobrir-se magicamente). você pode tirar vantagem deste momento, quando você tem a tarefa recém-criada e sua esquerda e pares certos, para dizer a todos que estão a sua vizinha (usando um rendez-vous, mais uma vez).

Outras dicas

O pacote Ada.Task_Identification fornece a função Current_Task para recuperar TASK_ID da tarefa atual.

Um par de coisas aqui.

Primeiro, Ada faz OO diferente que C ++. Não há "este" ponteiros na língua. Despacho é feito fora dos parâmetros. Uma implicação disso é que é possível para despachar fora de mais de um parâmetro, ao contrário do C ++. Isso é outra discussão para outro momento embora. Se você não gostar dele, você sempre pode nomear seu parâmetro despachar "isto".

Em segundo lugar, os conceitos de OO não se aplica realmente muito bem a objetos de simultaneidade como tarefas. Isso não é culpa de Ada. É um problema bem conhecido. Infelizmente, foi em vez sem imaginação denominado "A Concorrência problema", então referências a ele ficar congestionado com questões de programação em uma pesquisa no Google. A essência básica é que você pode fazer inheritence apoio objetos e expedição dinâmica e todas essas coisas boas, ou você pode fazê-los suportar a concorrência. Fazer ambos na mesma estrutura da linguagem é muito difícil.

Por uma questão de praticidade, se você precisa de um ponteiro para a sua própria tarefa, você pode torná-lo um global, ou ter a tarefa que aloca-lo passar o ponteiro em usar algum tipo de encontro initilization. Eu vi este feito antes, para ter uma tarefa em uma pilha de tarefas do trabalhador se colocar de volta na pilha "idle" quando ele terminar.

Mesmo que este tema é velho eu corri através dele procurando por algo semelhante a mim mesmo (a minha necessidade foi permitindo uma tarefa para passar um identificador de si mesmo para uma área de armazenamento mapa protegido hash que todas as tarefas têm acesso, em um efeito de registro) .

Você pode fazer isso em Ada de 2005, pensamos que não é recomendado porque ele desativa verificações de acesso, mas é a única maneira que eu encontrei para ter uma tarefa gerar (ou encontrar) o seu próprio punho para passar para funções de back chamada (por favor nota Isto não exclui TASK_ID passando para verificar se há Rescisão ou 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;

Gostaria de reorganizar o seu código se eu fosse você. Então, há algumas tarefas que interagem com outras tarefas, agora com 2 tarefas. E não há lista, que é responsável por armazenar as tarefas e gerenciar a inserção / exclusão de tarefas ligadas. Este é um objeto global que devem manusear sincronizado.

É por isso que eu aconselhá-lo a criar um objeto protegido, e armazenar a lista de tarefas dentro disso. A protegida é tipicamente utilizado para objectos passivos, onde algum recurso deve ser pega sincronizados. Você pode ter procedimentos como inserir, remover, etc. Isso irá garantir que apenas uma criação e remoção será executado em um momento, e a lista ligada não será inconsistente.

Cada tarefa deve saber que é tarefas "parceiro" que poderia mudar quando inserção ou remoção de uma tarefa. Eu aconselho a criar uma entrada para a tarefa que irá atualizar seus vizinhos. Quando as tarefas vir ou licença, o objeto protegido irá atualizar os vizinhos.

Neste caso, não há necessidade de acessar o ponteiro "este", porque o objeto protegido irá organizar tudo. Só é necessário um ID, que pode identificar a tarefa (para remoção).

Eu tento escrever o código, mas eu não tenho compilador agora:

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;
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top