Forums before death by AOL, social media and spammers... "We can't have nice things"
|    sci.electronics.design    |    Electronic circuit design    |    143,326 messages    |
[   << oldest   |   < older   |   list   |   newer >   |   newest >>   ]
|    Message 142,937 of 143,326    |
|    Don Y to Martin Brown    |
|    Re: Call by reference protection    |
|    20 Feb 26 10:47:43    |
      From: blockedofcourse@foo.invalid              On 2/20/2026 3:36 AM, Martin Brown wrote:       > On 19/02/2026 22:04, Don Y wrote:       >> Using similar mechanisms to those that I use in call-by-value RMIs,       >> I can protect against races for call-by-reference -- throwing an       >> exception or just spinning on any violations on the calling side.       >>       >> Or, I can just let people rely on their own discipline to       >> ensure they don't introduce latent bugs via this mechanism       >> (resorting to call by value universally seems a bad idea       >> for legacy coders). As these types of races have typically       >> been hard to test for, I suspect it is worth the effort.       >>       >> Any pointers to languages or IDLs that include such qualifying       >> adjectives?       >       > Languages that allow call by reference to be qualified with a const or       readonly       > directive so that the routine reading the original object (no copy made) is       not       > allowed to alter the it in any way.              That's a different problem.              A mutable object *intended* to be manipulated in the called scope       is EXPECTED to be altered by that invoked function.              Less obviously, another executing thread is likely NOT expected to       alter that object while the invoked function is executing!              While C doesn't really have cal-by-reference, the problem can       be illustrated using pointers instead of references. Consider:              object_t anObject;              // initialize anObject somehow       ...              // act on anObject through a pointer to it       operator(&anObject, ...)              // reference the expected changes in anObject in someway       ...              In a single threaded, single processor environment, one KNOWS that       nothing is dicking with anObject while operator() is running -- because       operator() has exclusive use of the processor.              Consequently, after operator() completes, one knows that anObject reflects       the operation performed by operator().              Add a second thread (or, second process having access to anObject).              Now, there is the possibility that the other actor can alter anObject while       operator() is executing -- likely without expecting such an interaction.       And, after operator() has concluded, the next line of code can't assume       that anObject reflects operator()'s actions.              [This can be avoided by using call-by-copy-restore but that just       ensures "the next line of code" works and does nothing for the       other problems]              The biggest exposure is likely from another thread in the same       process container acting on anObject alongside the thread that       is executing the above code. Adding explicit locks can avoid       this (at a cost and another level of discipline). A better approach       is to structure the code so this "doesn't (but CAN!) happen"              [Almost every piece of code in my system is a service or an agency.       As such, they all try to be N copies of the same algorithm running       on N different instances of objects of a particular type. Easy       if you *design* for that case; tedious if you adopt /ad hoc/       methods!]              When operator is an IPC/RPC/RMI, you have another can of worms as       as the window of vulnerability expands due to the extra overhead of       invocation along with those "external" actors (multiple processors       instead of just multiple threads/processes).              [Given the server/agent nature, all interactions will be non-local]              I use CoW to implement call-by-value semantics on objects that       would typically be passed as call-by-reference. E.g., imagine       anObject is a single frame of video and operator() is going to       apply a masking function to it, eliding all but the "important"       parts of the frame for return to the caller.              The instance of anObject shared between caller and callee can       then be isolated from other actors. You can emulate a "single       processor, single thread" environment with all of those impied       expectations.              If I then combine this with call-by-value-restore (for the       call-by-reference case), then anObject accurately reflects       the actions performed by operator() regardless of what other       competing actions may have transpired while operator() was       executing; those other actions occurred on a different instance       of anObject.              But, the cost to do so is high.              And, more significantly, I wonder if it makes bugs MORE likely       because "anObject" isn't *anObject* any longer. If buggy code       expected it to be so... |
[   << oldest   |   < older   |   list   |   newer >   |   newest >>   ]
(c) 1994, bbs@darkrealms.ca