[M3devel] idioms for tracking initialization state and raising errors?

Rodney M. Bates rodney_bates at lcwb.coop
Thu Sep 1 03:40:04 CEST 2016



On 08/31/2016 12:58 PM, Rodney M. Bates wrote:
>
>
> On 07/31/2016 04:07 AM, Jay K wrote:
>> Is this a correct idiom?
>> If so, I think it is fairly reasonable.
>>
>>
>> That is:
>>   be very willing to "early return"
>>   put all cleanup in finally
>>   raise errors in finally
>>
>>
>> In particular, I don't want to repeat the cleanup.
>> I don't want to raise before leaving critical sections.
>>
>>
>> I don't intend this to raise within a raise, but only
>> from the "normal" exit of the finally block.
>>
>>
>> I also don't want extra local booleans, i.e. raise: boolean to indicate failure.
>> Just the one to indicate success.
>>
>>
>> PROCEDURE InitMutex (mutex: Mutex) =
>>    VAR
>>      lock: PCRITICAL_SECTION := NIL;
>>      locked: PCRITICAL_SECTION := NIL;
>>
>>    BEGIN
>>      IF mutex.initialized THEN RETURN END;
>>
>>      TRY
>>
>>        lock := NewCriticalSection();
>>        IF lock = NIL THEN RETURN; END;
>>
>
>           ^I suggest moving the two statements above inside the critical
>            section on initLock, after the inner check on mutex.initialized.
>            That way, if we lose a race, it avoids executing creation then
>            deletion of an unneeded CriticalSection, and further eliminates
>            the cleanup action in the code.
>

Tony, is there some reason why, in ThreadPThread.m3, pthread_mutex_new can't be
done while holding initMu?  In initMutex, it is doing it the way Jay proposed,
i.e., allocate before getting initMu, which (the allocation) could turn out unnecessary
if we lose a race, then slightly later, freeing it, never used, if a lost race happened.


> BTW, I am assuming initLock is a single global CriticalSection?
>
>
>>        EnterCriticalSection(ADR(initLock));
>>        locked := ADR(initLock);
>>
>>        IF mutex.initialized THEN RETURN END;
>>
>>        (* We won the race. *)
>>        RTHeapRep.RegisterFinalCleanup (mutex, CleanMutex);
>>        mutex.lock := lock;
>>        lock := NIL;
>>        mutex.initialized := TRUE;
>>
>>      FINALLY
>>        IF locked # NIL THEN LeaveCriticalSection(locked); END;
>>        DelCriticalSection(lock);
>>        IF NOT mutex.initialized THEN (* Raise after leaving critical section. *)
>>          RuntimeError.Raise (RuntimeError.T.OutOfMemory);
>>        END;
>>      END;
>>
>>    END InitMutex;
>>
>>
>> Thank you,
>>   - Jay
>>
>>
>> _______________________________________________
>> M3devel mailing list
>> M3devel at elegosoft.com
>> https://m3lists.elegosoft.com/mailman/listinfo/m3devel
>>
>

-- 
Rodney Bates
rodney.m.bates at acm.org


More information about the M3devel mailing list