How to resolve the algorithm Mutex step by step in the E programming language

Published on 12 May 2024 09:40 PM
#E

How to resolve the algorithm Mutex step by step in the E programming language

Table of Contents

Problem Statement

A mutex (abbreviated Mutually Exclusive access) is a synchronization object, a variant of semaphore with k=1. A mutex is said to be seized by a task decreasing k. It is released when the task restores k. Mutexes are typically used to protect a shared resource from concurrent access. A task seizes (or acquires) the mutex, then accesses the resource, and after that releases the mutex. A mutex is a low-level synchronization primitive exposed to deadlocking. A deadlock can occur with just two tasks and two mutexes (if each task attempts to acquire both mutexes, but in the opposite order). Entering the deadlock is usually aggravated by a race condition state, which leads to sporadic hangups, which are very difficult to track down.

Let's start with the solution:

Step by Step solution about How to resolve the algorithm Mutex step by step in the E programming language

Source code in the e programming language

def makeMutex() {

    # The mutex is available (released) if available is resolved, otherwise it
    # has been seized/locked. The specific value of available is irrelevant.
    var available := null
    
    # The interface to the mutex is a function, taking a function (action)
    # to be executed. 
    def mutex(action) {
        # By assigning available to our promise here, the mutex remains 
        # unavailable to the /next/ caller until /this/ action has gotten
        # its turn /and/ resolved its returned value.
        available := Ref.whenResolved(available, fn _ { action <- () })
    }
    return mutex
}

Creating the mutex:

? def mutex := makeMutex()
# value: 

Creating the shared resource:

? var value := 0
# value: 0

Manipulating the shared resource non-atomically so as to show a problem:

? for _ in 0..1 {
>     when (def v := (&value) <- get()) -> {
>         (&value) <- put(v + 1)
>     }
> }

? value
# value: 1

The value has been incremented twice, but non-atomically, and so is 1 rather
than the intended 2.

? value := 0
# value: 0

This time, we use the mutex to protect the action.

? for _ in 0..1 { 
>     mutex(fn { 
>         when (def v := (&value) <- get()) -> { 
>             (&value) <- put(v + 1)
>         } 
>     })
> }

? value
# value: 2

  

You may also check:How to resolve the algorithm Mind boggling card trick step by step in the Rust programming language
You may also check:How to resolve the algorithm Show the epoch step by step in the Arturo programming language
You may also check:How to resolve the algorithm Lucas-Lehmer test step by step in the Pascal programming language
You may also check:How to resolve the algorithm Show the epoch step by step in the COBOL programming language
You may also check:How to resolve the algorithm Test a function step by step in the Ring programming language