From mboxrd@z Thu Jan 1 00:00:00 1970 X-Spam-Checker-Version: SpamAssassin 3.4.4 (2020-01-24) on polar.synack.me X-Spam-Level: X-Spam-Status: No, score=0.7 required=5.0 tests=BAYES_00,INVALID_DATE, REPLYTO_WITHOUT_TO_CC autolearn=no autolearn_force=no version=3.4.4 Xref: utzoo comp.lang.c++:12877 comp.lang.ada:5246 Path: utzoo!utgpu!news-server.csri.toronto.edu!cs.utexas.edu!swrinde!zaphod.mps.ohio-state.edu!uakari.primate.wisc.edu!xanth!cs.odu.edu!zeil From: zeil@cs.odu.edu (Steven J. Zeil) Newsgroups: comp.lang.c++,comp.lang.ada Subject: Hiding Concurrency Message-ID: <1991Apr15.211346.15760@cs.odu.edu> Date: 15 Apr 91 21:13:46 GMT Sender: usenet@cs.odu.edu (Usenet News Poster) Reply-To: zeil@cs.odu.edu (Steven J. Zeil) Organization: Old Dominion University, Norfolk, VA Nntp-Posting-Host: dolphin.cs.odu.edu List-Id: While reviewing some code for portability problems, I recently became suspicious of a rather ugly case of "feature interaction" in Ada. Consider the following package, intended for use in concurrent applications: with Semaphores; -- assume a reasonable definition with Attribute_Types; use Attribute_Types; package ADTs is type ADT is limited private; function Attribute1 (A: ADT) return Attribute1_Type; procedure Put_Attribute1 (A: in out ADT; Attr_Value : in Attribute1_Type); function Attribute2 (A: ADT) return Attribute2_Type; procedure Put_Attribute2 (A: in out ADT; Attr_Value : in Attribute2_Type); ADT_Instance : ADT; private type ADT is record Controller : Semaphores.Semaphore; Attr1 : Attribute1_Type; Attr2 : Attribute1_Type; end record; end ADTs; package body ADTs is use Semaphores; function Attribute1 (A: ADT) return Attribute1_Type is Attr : Attribute1_Type; begin Seize (A.Controller); Attr := A.Attr1; Release (A.Controller); return Attr; edn Attribute1; procedure Put_Attribute1 (A: in out ADT; Attr_Value : in Attribute1_Type) is begin Seize (A.Controller); A.Attr1 := Attr_Value; Release (A.Controller); end Put_Attribute1; . . and so on . end ADTs; Now, it looks to me as if I have done all the proper and careful things to protect my ADT objects during concurrent access, while hiding that protection behind the procedural interface just in case I later want an unprotected form of the same ADT for use in non-concurrent applications. But how safe is this, really, if the compiler exercises its option to pass parameters by copy-in/copy-out? Suppose that I have one task that attempts: Put_Attribute1 (ADT_Instance, X); just as another is about to attempt: Put_Attribute2 (ADT_Instance, X); It appears to me that I could get in trouble if the first task is only part-way through copying the ADT value back out when the second begins copying it in. Similar problems seem to occur if the second task instead were attempting to call the Attribute1 function, and possibly even the Attribute2 function. These problems do not arise if the compiler opts to pass the ADT parameters by reference. My conclusion is that hiding concurrency control among operations with "in out" parameters behind a procedural interface is generally "erroneous" (in the sense that LRM 6.2.7 declares all program executions erroneous whose "effect depends on which [parameter passing] mechanism is selected by the implementation.") To get around this, I would need to either make all of the operations explicit task entries, in which case I cannot easily later replace this package with a sequential version, or I must redesign the interface to eliminate all but "in" parameters among the operations that could be called "simultaneously". Most likely, this means redefining ADT as a pointer to the record structure used above. Such a redefinition is plausible, but may have other unfortunate and far-reaching consequences. Does anyone see a flaw in my analysis of this problem? Steve Zeil