سؤال

على وجه التحديد، هل هناك طريقة لمهمة الحصول على مرجع إلى نفسه؟

علي سبيل المثال:

task type someTask; 
type someTaskAccessor is access someTask;

task body someTask is
    pointerToTask : someTaskAccessor;
begin
    pointerToTask = this;
end someTask;
هل كانت مفيدة؟

المحلول

الحل الأكثر وضوحا يمكن أن أقترح هو إعلان Rendez-vous (دخول) في بداية مهمتك، والتي تقوم بها مرجعا إلى المهمة التي تم إنشاؤها للتو. الاحتمال الآخر يستخدم تمييزا عن نوع المهام الخاص بك، الذي يدور دوره هو سرد مهمة جديدة حيث يقع (تمر الوصول إلى المهمة الجديدة في التمييز). لسوء الحظ، ليس لدي مترجم ADA في متناول اليد، لذلك لا أستطيع أن أعطيك أي مثال على العمل.

على أي حال، بناء على تعليقك: يجب التعامل مع إنشاء مهمة جديدة في مكان ما، عند النقطة التي ستحتاج أيضا إلى تحديد مكان هذه المهمة الجديدة ستذهب إلى قائمتك المرتبطة مضاعفة (تحتاج إلى معرفة مهمة حالية واحدة على الأقل عند إنشاء واحدة جديدة من أجل التواصل: إنهم لن يكتشفوا أنفسهم بطريقة سحرية). يمكنك الاستفادة من هذه اللحظة، عندما يكون لديك المهمة التي تم إنشاؤها حديثا وأقرانها الأيمن والأيمن، لإخبار الجميع الذين هم جارهم (باستخدام Rendez-vous مرة أخرى).

نصائح أخرى

حزمة ada.task_didentification. يوفر وظيفة Current_Task لاسترداد مهمة المهام الحالية.

زوجان من الأشياء هنا.

أولا قبالة، ADA لا أحد بشكل مختلف أن C ++. لا توجد مؤشرات "هذه" باللغة. يتم إرسال الإرسال قبالة المعلمات. هناك تأثير واحد على ذلك أنه من الممكن إرسال أكثر من معلمة واحدة، على عكس C ++. هذا مناقشة أخرى لمرة أخرى على الرغم من ذلك. إذا كنت لا تحب ذلك، يمكنك دائما تسمية معلمة الإرسال الخاصة بك "هذا".

ثانيا، لا تنطبق مفاهيم OO حقا جيدا على اعتزام الكائنات مثل المهام. هذا ليس خطأ ada. إنها مشكلة معروفة. للأسف، كان الأمر غير طبيعي تماما "مشكلة التزامن"، لذا فإن الإشارة إليها تغرق مع مشكلات البرمجة على بحث Google. GIST الأساسي هو أنه يمكنك إجراء وراثة دعم الكائنات والإرسال الديناميكي وكل تلك الأشياء الجيدة، أو يمكنك أن تجعلها تدعم التزامن. القيام كلاهما في نفس هيكل اللغة أمر صعب للغاية.

كمسألة عملية، إذا كنت بحاجة إلى مؤشر مهمتك، فيمكنك إما أن تجعلها مهمة، أو لديك المهمة التي تخصصها تمرير المؤشر في استخدام نوع من بدء التشغيل. لقد رأيت هذا القيام به من قبل، أن يكون لديك مهمة في كومة من مهام العمال وضعت نفسها على مكدس "الخمول" عندما تنتهي.

على الرغم من أن هذا الموضوع قديم، إلا أنني ركضت عبرها بحثا عن شيء مماثل لنفسي (حاجتي كانت تسمح بمهمة اجتياز مقبض لنفسها إلى منطقة تخزين خريطة التجزئة المحمية التي يمكن لجميع المهام الوصول إليها، في التأثير على التسجيل).

يمكنك القيام بذلك في 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. وهناك قائمة مرتبطة، وهي مسؤولة عن تخزين المهام وإدارة الإدراج / حذف المهام. هذا كائن عالمي يجب أن يتعامل مع المتزامنة.

لهذا السبب أنا نصصحك بإنشاء كائن محمي، وتخزين قائمة المهام داخل ذلك. عادة ما يتم استخدام المحمية للأشياء السلبية، حيث يجب معالجة بعض المورد متزامنة. يمكنك الحصول على إجراءات مثل إدراج، وإزالتها إلخ. سيضمن ذلك إنشاء إنشاء وإزالة واحد فقط في كل مرة، ولن تكون القائمة المرتبطة غير متناسقة.

يجب أن تعرف كل مهمة مهام "الشريك" التي قد تتغير عند إدراج أو إزالة المهمة. أنا نصيحة إنشاء إدخال في المهمة التي ستقوم بتحديث جيرانها. عندما تأتي المهام أو إجازة، سيقوم الكائن المحمي بتحديث الجيران.

في هذه الحالة، لا حاجة للوصول إلى المؤشر "هذا"، لأن الكائن المحمي سوف ينظم كل شيء. مطلوب معرف فقط، والتي يمكن أن تحدد المهمة (للإزالة).

أحاول كتابة التعليمات البرمجية، لكن ليس لدي مترجم الآن:

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