Hi, I need to mutually exclude 2 function class bu...
# coroutines
u
Hi, I need to mutually exclude 2 function class but each is from a different class
Copy code
class SerializedGate {
    private val mutex = Mutex()

    suspend fun run(block: suspend () -> Unit) {
        mutex.withLock {
            block()
        }
    }
}

class ClassA(private val gate: SerializedGate) {
    suspend fun publicFunctionA() {
        gate.run {
            // A work
        }
    }
}

class ClassB(private val gate: SerializedGate) {
    suspend fun publicFunctionB() {
        gate.run {
            // B work
        }
    }
}
This is what I have and seems to work but I feel odd about it (as I've only used mutex as a internal detail effectively within a single class) Is this idiomatic?
y
That looks correct to me. Only note I'd have is to change
run
to something else just because there's the stdlib
.run
function, and so it might be confusing. What you've basically done is abstracted over a mutex into a less-powerful construct, which is aboslutely fine!
u
so you'd say mutex is the correct idiom? isnt it too low level?
y
It depends on what you're trying to do. Your example seems to need "mutual exclusion", hence a mutex is apt.
u
yea but im used to "mutex" being a thread thing, this seems a higher level thing but okay thanks!
okay ill do a quick snippet
y
Kotlin
Mutex
is not necessarily thread-related. It actually uses coroutines, while a normal Java-style Lock would not even function properly.
u
Copy code
class SerializedGate {
    private val mutex = Mutex()

    suspend fun run(block: suspend () -> Unit) {
        mutex.withLock {
            block()
        }
    }
}

class ClassA(private val gate: SerializedGate) {
    suspend fun publicFunctionA() {
        gate.run {
        	val foo = db.loadFoo()
        	val isSelected = apiCall(foo) <--- suspend between synchornous db read and write
            db.updateFoo(foo.id, isSelected)
        }
    }
}

class ClassB(private val gate: SerializedGate) {
    suspend fun publicFunctionB() {
        gate.run {
        	val foo = db.loadFoo()
        	val isSelected = apiCall(foo) <--- suspend between synchornous db read and write
            db.updateFoo(foo.id, isSelected)
        }
    }
}
+- this is what I'm trying to do the issue is
foo
changing between loadFoo and updateFoo usually i'd stick this in a db transaction - but api call is suspend function which breaks it (db tx are synchronous)
so I need to serialize the whole thing between 2 classes that need to updateFoo (obviously the snippet doesnt really make sense as its copy paste, just for sake of brevity)