GuardedByLock a simple helper to make sure variable is only accessed with lock
A topic of ownership is better covered in Rust Language. Still, such problems are not solved well enough in the JVM world. Let’s consider a trivial shared state access example
We all know the best state is no state. And we tend to decouple tricky things. But of course, there are some places in programs where one finally needs to deal with a state. In reality, it can easily be a complicated state with several different locks in one object.
The common problem here is to make sure fields are accessed with correct locks taken. It is tricky to ensure in Java. It is double tricky to ensure future changes will not break the contract.
JSR-305 and GuardedBy annotations are created to make a binding between state and guards. But those are only to help an IDE to be smarter, those annotations will not turn a mistake into a compilation error.
I’m looking the way to make a compiler to ensure the access is correct.
Java Style solution
In Java, this can be done in the following way. Create a function
runWithLock and make this function accept
an interface with a method like
run(State s). If necessary a generics can be added to simplify usages.
To implement that one need to extract a state object (which I call
State). Happy Java 1.8 users may benefit
from Lambda syntax. But the approach itself requires a creation of tiny objects (for lambdas, in most cases) on every call.
Such overhead is small, but one may not like it.
An example call code would look like
Let’s try avoid lambdas overhead and to yield a bit better syntax.
Kotlin Style solution
Consider the following implementation in Kotlin
The usage is as follows:
Let’s take a look closer to the
runWithLock call. Here
} are used to
declare an anonymous extension function
State.() -> Y (
Y is a generic type parameter).
Extension function means that in the body of the function we have
this keyword pointing to
instance. And the part
value = 5 means we assign the value to
State object property/field.
inline keyword here makes Kotlin compiler to
the function body to avoid creating an anonymous function in the compiled code. You may refer to
the previous post for bytecode listing of inline function calls.
With this approach, we avoid creation anonymous classes for Lambdas from one hand. From the other hand,
the Kotlin compiler is in charge of checking a
State object instance in only accessible after necessary
locks are held.
Finally, the bytecode for the
main function is the following. Note. I use IntelliJ IDEA 2017.1 EAP with Kotlin
1.0.6 plugin. The generated bytecode may change with a future version of tools.
As we see from the code, there is NO anonymous class creation.A call to
GuardedByLock#runWithLock was inlined into
main function body, meaning less overhead (who’d measure it :).
In the post, I presented
GuardedByLock class in Kotlin. Using it in your project may help to
correctly isolate state and make Kotlin complier checking all possible violations for you.
The only cost is 2 additional object instances: one for
GuardedByLock, and the other one for the