具體來說,是否有任務獲取對自身的引用?Ada中是否有「this」關鍵字?
例如:
task type someTask;
type someTaskAccessor is access someTask;
task body someTask is
pointerToTask : someTaskAccessor;
begin
pointerToTask = this;
end someTask;
具體來說,是否有任務獲取對自身的引用?Ada中是否有「this」關鍵字?
例如:
task type someTask;
type someTaskAccessor is access someTask;
task body someTask is
pointerToTask : someTaskAccessor;
begin
pointerToTask = this;
end someTask;
我可以建議的最明顯的解決方案是在任務開始時聲明一個rendez-vous(一個條目),並將引用傳遞給剛剛創建的任務。另一種可能性是對你的任務類型使用判別式,它的作用是告訴它所在的新任務(將新任務的訪問傳遞給判別式)。不幸的是,我手邊沒有Ada編譯器,所以我不能給你任何工作的例子。
無論如何,根據你的評論:創建一個新任務需要在某個地方處理,此時你還需要確定這個新任務將進入你的雙向鏈表(你需要知道的地方當創建一個新的任務以便他們溝通時,至少有一個現有任務:他們不會神奇地發現自己)。你可以利用這一時刻,當你有新創建的任務和左右同伴時,告訴每個人誰是他們的鄰居(再次使用rendez-vous)。
這實際上是我提出這個問題後不久提出的解決方案:) – Landon
它也是正確的答案。我會接受它是我。 –
包Ada.Task_Identification提供Current_Task函數來檢索當前任務的TASK_ID。
是啊,我看到了,但你可以檢索與該ID的指針? – Landon
你爲什麼要這樣? –
看看包裝Ada.Task_Attributes(在2005年的Ada LRM C.7.2)。讓我們將一個通用屬性(如任務指針或句柄)與用戶定義的數據塊關聯起來,並將其與任務實例相關聯。警告:我從來沒有親自使用這個軟件包,我只是通過LRM。 –
如果我是你,我會重新組織你的代碼。所以,有一些任務與其他任務交互,現在有兩個任務。並且有鏈接列表,它負責存儲任務並管理任務的插入/刪除。這是一個應該同步處理的全局對象。
這就是爲什麼我建議你創建一個受保護的對象,並在其中存儲任務列表。保護通常用於被動對象,其中一些資源必須處理同步。你可以有像插入,刪除等程序。這將確保一次只有一個創建和刪除運行,並且鏈接列表不會不一致。
每個任務應該知道它是「合作伙伴」的任務,這些任務在插入或移除任務時可能會改變。我建議創建一個可以更新其鄰居的任務。當任務進入或離開時,受保護的對象將更新鄰居。
在這種情況下,不需要訪問「this」指針,因爲受保護的對象會組織一切。只需要一個ID,它可以識別任務(用於刪除)。
我嘗試寫的代碼,但我沒有編譯器現在:
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;
幾件事情在這裏。
首先,Ada的OO與C++不同。該語言中沒有「this」指針。調度是通過參數完成的。其中一個含義是,與C++不同,它可以從多個參數中分派出來。儘管如此,這是另一次討論。如果你不喜歡它,你總是可以將你的調度參數命名爲「this」。其次,面向對象的概念並不能很好地適用於像任務這樣的併發對象。這不是阿達的錯。這是一個衆所周知的問題。令人遺憾的是,它被稱爲「併發問題」頗爲無法想象,因此在谷歌搜索中引用了它的編程問題。基本的要點是你可以使對象支持繼承和動態分派以及所有好東西,或者你可以讓它們支持併發。在相同的語言結構中做這兩件事非常困難。
由於實用性的問題,如果你需要一個指向自己的任務,你可以使它成爲一個全球性的,或有分配它通過指針在使用某種動初始化會合的任務。我見過這樣做過,能有在工人的任務堆棧任務把自己放回「空轉」堆棧當它完成。
即使這個話題是老我碰到它跑尋找類似的自己(我的需要是允許一個任務的句柄傳遞給自己的所有任務具有訪問受保護的哈希映射存儲區的東西,在影響登記)。
你可以在Ada 2005中做到這一點,認爲它不被推薦,因爲它禁用了訪問檢查,但它是我發現有一個任務生成(或找到)它自己的句柄傳入回調函數的唯一方法(請注意這並不排除Task_ID通過檢查Termination或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;
你也可以在Ada 95(和2012)中做到這一點。另外,'pointerToTask'應該聲明爲'constant'。 –
你想達到什麼目的? –
我正在實施分散互斥算法。每個進程(節點)只知道它的左邊和右邊的鄰居(指向進程的指針)。該過程形成雙向鏈表,所以,流程的刪除和插入要求其鄰居更新他們的鄰居的指針,因此,當一個進程插入本身,它必須指向發送到自己的鄰居。我可以只通過整數/ Task_IDs,但隨後的指針將在一個表中,這將使實施更爲分散來進行查找。 – Landon
啊。好。那麼你大多會對我答案的最後一段感興趣。 –