[M3devel] idioms for tracking initialization state and raising errors?
Rodney M. Bates
rodney_bates at lcwb.coop
Thu Sep 1 17:03:43 CEST 2016
OK, on that basis, I withdraw the suggestion about allocating the PCRITICAL_SECTION
while locked. In any case, the wasted allocate/delete would probably be rare.
On 08/31/2016 11:18 PM, Hosking, Antony L wrote:
> I may have been suspicious about internal locking within pthread_mutex_new, but don’t recall precisely. It might even have been a deadlock bug that I encountered. In general I don’t like library calls inside the mutex blocks - just the state changes I am really trying to protect.
>
>> On 1 Sep 2016, at 11:40 AM, Rodney M. Bates <rodney_bates at lcwb.coop> wrote:
>>
>>
>>
>> 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
>> _______________________________________________
>> 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