Question

Plus précisément, est-il un moyen pour une tâche d'obtenir une référence à lui-même?

Par exemple:

task type someTask; 
type someTaskAccessor is access someTask;

task body someTask is
    pointerToTask : someTaskAccessor;
begin
    pointerToTask = this;
end someTask;
Était-ce utile?

La solution

la solution la plus évidente que je pourrais suggérer est de déclarer un rendez-vous (une entrée) au début de votre tâche, à laquelle vous passez une référence à la tâche vient d'être créé. l'autre possibilité est d'utiliser un discriminante à votre type de tâche, dont le rôle est de dire une nouvelle tâche où il se trouve (passer l'accès à la nouvelle tâche dans le discriminante). malheureusement, je n'ai pas un compilateur Ada à la main donc je ne peux pas vous donner un exemple de travail.

de toute façon, en fonction de votre commentaire: la création d'une nouvelle tâche doit être traitée quelque part, à quel point vous aurez également besoin de déterminer où cette nouvelle tâche sera dans votre liste doublement chaînée (vous devez savoir au moins une tâche existante lorsque pour les créer un nouveau afin de communiquer: ils ne seront pas se découvrir comme par magie). vous pouvez profiter de ce moment, lorsque vous avez la tâche nouvellement créée et ses pairs à gauche et à droite, pour dire tous ceux qui sont leurs voisins (en utilisant une fois de plus rendez-vous).

Autres conseils

Le paquet Ada.Task_Identification fournit la fonction Current_Task pour récupérer TASK_ID de la tâche en cours.

Un couple de choses ici.

Tout d'abord, Ada ne OO différemment que C ++. Il n'y a pas « ce » pointeurs dans la langue. Dispatching se fait hors des paramètres. L'une des conséquences de cela est qu'il est possible d'envoyer au large de plus d'un paramètre, contrairement à C ++. C'est une autre discussion pour une autre fois cependant. Si vous ne l'aimez pas, vous pouvez toujours le nom de votre paramètre dispatching « this ».

En second lieu, les concepts OO ne sont pas applicables vraiment très bien à des objets comme des tâches de concurrence. Ce n'est pas la faute d'Ada. Il est un problème bien connu. Malheureusement, il a été plutôt appelé unimaginatively « Le problème Concurrency », donc des références à ce être submergé de questions de programmation sur une recherche google. L'essentiel de base est que vous pouvez faire des objets prennent en charge inheritence et l'expédition dynamique et toutes ces bonnes choses, ou vous pouvez les faire soutenir la concurrence. Faire les deux dans la même structure linguistique est très difficile.

En pratique, si vous avez besoin d'un pointeur vers votre propre tâche, vous pouvez faire une approche globale, ou la tâche qui attribue passer le pointeur à l'aide d'une sorte de rendez-vous initilization. Je l'ai vu cela avant, d'avoir une tâche dans une pile de tâches de travail lui-même remis sur la pile « ralenti » quand il se termine.

Même si ce sujet est vieux, je courais à travers elle cherche quelque chose me similaire (mon besoin permettais une tâche de passer une poignée à lui-même pour une zone de stockage de carte de hachage protégée que toutes les tâches ont accès, dans une incidence sur l'enregistrement) .

Vous pouvez le faire en Ada 2005, pensé que ce n'est pas recommandé car il désactive les contrôles d'accès, mais il est la seule façon que j'ai trouvé une generate (ou trouver) son propre poignée de passer dans rappel des fonctions (s'il vous plaît noter cela ne fait pas obstacle à passer TASK_ID pour vérifier résiliation 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;

Je réorganise votre code si je vous étais. Donc, il y a des tâches qui interagissent avec d'autres tâches, maintenant avec 2 tâches. Et il est lié liste, qui est chargé de stocker les tâches et gérer l'insertion / suppression des tâches. Ceci est un objet global qui doit gérer synchronisée.

Voilà pourquoi je vous conseille de créer un objet protégé, et stocker la liste des tâches à l'intérieur que. La protection est généralement utilisé pour des objets passifs, où une ressource doit être poignée synchronisée. Vous pouvez avoir des procédures telles que l'insertion, supprimer, etc. Cela garantira que seule la création et le retrait sera en cours d'exécution à la fois, et la liste chaînée ne sont incompatibles.

Chaque tâche doit connaître ses tâches « partenaires » qui pourrait changer lors de l'insertion ou la suppression d'une tâche. Je conseille la création d'une entrée dans la tâche qui mettra à jour ses voisins. Lorsque les tâches viennent ou quittent, l'objet protégé mettra à jour les voisins.

Dans ce cas, pas besoin d'accéder au pointeur « this », parce que l'objet protégé organisera tout. Seul un ID est nécessaire, ce qui permet d'identifier la tâche (pour le retrait).

J'essaie d'écrire le code, mais je n'ai pas compilateur maintenant:

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;
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top