[M3devel] to share code between Join and AlertJoin or not?

Jay K jay.krell at cornell.edu
Sat Dec 12 16:25:44 CET 2009


Here's a case where it is not clear if the code is worth sharing:

 

 

Join and AlertJoin share XJoin:

 

 

PROCEDURE XJoin (t: T; alertable: BOOLEAN): REFANY RAISES {Alerted} =
  VAR (* The order of the handles is important. *)
      handles := ARRAY [0..1] OF HANDLE {t.act.handle, NIL(*alertEvent*)};
      wait: DWORD;
  BEGIN
    IF t.joined # 0 THEN Die(ThisLine(), "attempt to join with thread twice") END;
    IF alertable THEN
      handles[1] := GetActivation().alertEvent;
    END;
    wait := WaitForMultipleObjects(1 + ORD(alertable), ADR(handles[0]), 0, INFINITE);
    <* ASSERT wait # WAIT_TIMEOUT *>
    <* ASSERT wait = WAIT_OBJECT_0 OR wait = (WAIT_OBJECT_0 + 1) *>
    IF wait = WAIT_OBJECT_0 THEN
      t.joined := 1;
      RETURN t.result;
    ELSE
      <* ASSERT wait = WAIT_OBJECT_0 + 1 *>
      <* ASSERT alertable *>
      RAISE Alerted;
    END;
  END XJoin;

 

 

PROCEDURE Join(t: T): REFANY =
  <*FATAL Alerted*>
  BEGIN
    IF DEBUG THEN ThreadDebug.Join(t); END;
    RETURN XJoin(t, alertable := FALSE);
  END Join;

PROCEDURE AlertJoin(t: T): REFANY RAISES {Alerted} =
  BEGIN
    IF DEBUG THEN ThreadDebug.AlertJoin(t); END;
    RETURN XJoin(t, alertable := TRUE);
  END AlertJoin;

 

 

OR without code sharing, it'd go like:

 

 

PROCEDURE Join(t: T): REFANY =
  VAR wait: DWORD;
  BEGIN
    IF t.joined # 0 THEN Die(ThisLine(), "attempt to join with thread twice") END;
    wait := WaitForSingleObject(t.act.handle, INFINITE);
    <* ASSERT wait = WAIT_OBJECT_0 *>
    t.joined := 1;
    RETURN t.result;
  END Join;

 


PROCEDURE AlertJoin (t: T): REFANY RAISES {Alerted} =
  VAR (* The order of the handles is important. *)
      handles := ARRAY [0..1] OF HANDLE {t.act.handle, GetActivation().alertEvent};
      wait: DWORD;
  BEGIN
    IF t.joined # 0 THEN Die(ThisLine(), "attempt to join with thread twice") END;
    wait := WaitForMultipleObjects(2, ADR(handles[0]), 0, INFINITE);
    <* ASSERT wait # WAIT_TIMEOUT *>
    <* ASSERT wait = WAIT_OBJECT_0 OR wait = (WAIT_OBJECT_0 + 1) *>
    IF wait = WAIT_OBJECT_0 THEN
      t.joined := 1;
      RETURN t.result;
    ELSE
      <* ASSERT wait = WAIT_OBJECT_0 + 1 *>
      RAISE Alerted;
    END;
  END AlertJoin;



anyone have strong feelings either way?

 

 

If we used win32 alertable waits, then the case for code sharing would be stronger, it'd go like:

 

 

 

PROCEDURE XJoin (t: T; alertable: BOOLEAN): REFANY RAISES {Alerted} =
  VAR wait: DWORD;
  BEGIN
    IF t.joined # 0 THEN Die(ThisLine(), "attempt to join with thread twice") END;
    wait := WaitForSingleObjectEx(t.act.handle, INFINITE, ORD(alertable));
    <* ASSERT wait = WAIT_OBJECT_0 OR wait = WAIT_IO_COMPLETION*>
    IF wait = WAIT_OBJECT_0 THEN
      t.joined := 1;
      RETURN t.result;
    ELSE
      <* ASSERT alertable *>
      RAISE Alerted;
    END;
  END XJoin;

 


 - Jay
 		 	   		  
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://m3lists.elegosoft.com/pipermail/m3devel/attachments/20091212/92a0868b/attachment-0001.html>


More information about the M3devel mailing list