How to check and also set variable synchronously in Kotlin? - asynchronous

I have a mutable nullable property. I'd like to check in a method if its value is null, if so, set it to a newly created object. Then I'd call a method of the property (old or new, but existing object).
And this should be thread-safe. How can I do that in Kotlin?
With .let, I cannot reassign the property. When using synchronized(...) or .withLock, between the assignment and invocation, the thread can be interrupted by another. Or at least the IDE says so, smart cast is impossible. I don't understand, why is synchronized there if it doesn't synchronize the block?
var starterTask: AsyncTask<MyData, Void, Void>? = null
fun start() {
make it thread safe {
if (starterTask == null) {
starterTask = a child of AsyncTask()
}
starterTask.execute(this) // <- no !! operator
}
}
In Java, if I locked an object with synchronized, I could check, assign, invoke an object, everyone was happy. Can I do the same in Kotlin?

You can use a delegated property for that:
val starterTask = lazy { a child of AsyncTask() }
fun start() {
starterTask.execute(this)
The default thread safety mode is SYNCHRONIZED, so it matches your needs.

Related

Cleaning up bindings and change listeners on nested properties when parent properties change in javafx

I have a model class with SimpleXXXXProperty properties. Javafx GUI elements are updated using either bindings or change listeners, e.g.
textField.textProperty().bind(myModel.myModelStatus());
or
myModel.myModelStatus().addListener((obj,oldv.newv) -> { update here });
When the instance of the model class changes, I rebind the controls and add the listeners again. However, I can see by the memory use that the old model still persists in memory.
What do I have to do to remove all references to the model so it can be cleaned up?
Unbind before binding again
Remove the listeners
Both
Is there are more automatic way of updating bindings and listeners on nested properties when the parent property changes?
Points to consider when you want to undo bindings (including listeners) to your model:
Undirectional bindings (p1.bind(p2)) are automatically unbound when binding the same property again (e.g. p1.bind(p3)), but it does not hurt to do it explicitely (p1.unbind()).
Bidirectional bindings (p1.bindBidirectional(p2) or Bindings.bindBidirectional(p1, p2)) have to be unbound explicitely (p1.unbindBidirectional(p2) or Bindings.unbindBidirectional(p1, p2)).
Listeners must be unregistered (prop.removeListener(l)).
The third is the tricky part, as listeners are often implemented as lambda expressions or method references. Unfortunately, lambda expressions as well as method references(!) are not constant:
// lambdas are not constant
InvalidationListener l1 = obs -> {};
InvalidationListener l2 = obs -> {};
assert l1 != l2; // they are NOT identical!
Well, this might be obvious for lambdas, but the same is also true for method references, which is really annoying:
// method references are not constant
Runnable runnable1 = this::anyMethod;
Runnable runnable2 = this::anyMethod;
assert runnable1 != runnable2; // they are NOT identical!
That means, you cannot register a lambda expression or a simple method reference as listener if you want to be able to unregister it:
// if you register listeners on a property like that...
label.textProperty().addListener(obs -> System.out.println(obs));
label.textProperty().addListener(this::handleLabelInvalid);
// ...these calls WON'T remove them due to the inequality shown above!
label.textProperty().removeListener(obs -> System.out.println(obs));
label.textProperty().removeListener(this::handleLabelInvalid);
Solution
You have to store a reference to the lambda expression or method referency by yourself. I use to use final fields for that:
public class MyClass {
// store references for adding/removal
private final InvalidationListener l1 = this::handleLabelInvalid;
private final InvalidationListener l2 = obs -> System.out.println(obs);
...
public void bind() {
label.textProperty().addListener(l1);
label.textProperty().addListener(l2);
}
public void unbind() {
label.textProperty().removeListener(l1);
label.textProperty().removeListener(l2);
}
private void handleLabelInvalid(Observable observable) { ... }
}

Access Kotlin Delegate Type without an Instance

I have read Access property delegate in Kotlin which is about accessing a delegate from an instance. One can use KProperty::getDelegate since Kotlin 1.1, however this will return the instance of the delegate and therefore needs an instance of the class first.
Now I want to get the type of the delegate without having an instance of the class. Consider a library with a custom delegate type CustomDelegate that want's to get all properties of a class that are delegated to an instance of CustomDelegate:
class Example
{
var nonDelegatedProperty = "I don't care about this property"
var delegatedProperty1 by lazy { "I don't care about this too" }
var delegatedProperty2 by CustomDelegate("I care about this one")
}
How can I, given I have KClass<Example>, but not an instance of Example, get all properties delegated to CustomDelegate?
How can I, given I have KClass<Example>, but not an instance of
Example, get all properties delegated to CustomDelegate?
You can do it in two ways depending on your needs.
First of all, you have to include the kotlin-reflect dependency in your build.gradle file:
compile "org.jetbrains.kotlin:kotlin-reflect:1.1.51"
In my opinion, you should use the first solution if you can, because it's the most clear and optimized one. The second solution instead, can handle one case that the first solution can't.
First
You can loop an the declared properties and check if the type of the property or the type of the delegate is CustomDelegate.
// Loop on the properties of this class.
Example::class.declaredMemberProperties.filter { property ->
// If the type of field is CustomDelegate or the delegate is an instance of CustomDelegate,
// it will return true.
CustomDelegate::class.java == property.javaField?.type
}
There's only one problem with this solution, you will get also the fields with type CustomDelegate, so, given this example:
class Example {
var nonDelegatedProperty = "I don't care about this property"
val delegatedProperty1 by lazy { "I don't care about this too" }
val delegatedProperty2 by CustomDelegate("I care about this one")
val customDelegate = CustomDelegate("jdo")
}
You will get delegatedProperty2 and customDelegate. If you want to get only delegatedProperty2, I found an horrible solution that you can use if you need to manage this case.
Second
If you check the source code of KPropertyImpl, you can see how a delegation is implemented. So, you can do something like this:
// Loop on the properties of this class.
Example::class.declaredMemberProperties.filter { property ->
// You must check in all superclasses till you find the right method.
property::class.allSuperclasses.find {
val computeField = try {
// Find the protected method "computeDelegateField".
it.declaredFunctions.find { it.name == "computeDelegateField" } ?: return#find false
} catch (t: Throwable) {
// Catch KotlinReflectionInternalError.
return#find false
}
// Get the delegate or null if the delegate is not present.
val delegateField = computeField.call(property) as? Field
// If the delegate was null or the type is different from CustomDelegate, it will return false.
CustomDelegate::class.java == delegateField?.type
} != null
}
In this case, you will get only delegatedProperty2 as result.

Unexpected Behavior passing weak reference in lambda

If I use this code, the function returns me null as the Resolve worked sometimes and failed sometimes (based on when this was called)
Platform::WeakReference wr(this);
Windows::Foundation::Collections::IAsyncOperation<Object1^>^ asyncTask =
concurrency::create_async(
[wr, timeoutMS](concurrency::cancellation_token token) -> Object1^
{
if (auto refToThis = wr.Resolve<CurrentClass>())
{
// Do something
}
else return null; // The code took this path if the call was made
// immediately, if the call was made from inner
// page or
// even after 5 sec in Main Page init – It always
// worked
}
Where as if I pass this reference in lambda expression it always resolves
Platform::WeakReference wr(this);
Windows::Foundation::Collections::IAsyncOperation<Object1^>^ asyncTask =
concurrency::create_async(
[this, wr, timeoutMS](concurrency::cancellation_token token) -> Object1^
{
if (auto refToThis = wr.Resolve<CurrentClass>())
{
// Do something - It resolves always now
}
else return null;
}
Any clue why this happens? I am new to C++/Cx, I read that its not good to pass this ref in lambda expressions, but the resolve fails if I dont pass
Why the second example always work:
You are capturing this in the lambda closure [], means you are doing a copy of this inside the lambda scope. Since this is probably a ref class it means you increment the reference counter of the pointer on it, meaning this will not be destroyed. When resolving the weak reference, since this is still alive, you are able to retrieve it from the weak reference.
In the first example, you are passing only the weak reference to the lambda closure, since you are probably working with some UI element, if this is destroyed, the weak reference resolution will return nullptr.
You should either pass a weak reference or directly this in the lambda closure, but in the case where you pass this, you should ensure that you will be called by this lambda in order to avoid keeping a reference on an object causing it to never be deleted, creating a memory leak.

Writing a Kotlin util function which provides self-reference in initializer

I'm trying to generalize my hack from an answer to another question.
It should provide a way to reference a value which is not constructed yet inside its initializer (of course, not directly, but in lambdas and object expressions).
What I have at the moment:
class SelfReference<T>(val initializer: SelfReference<T>.() -> T) {
val self: T by lazy {
inner ?: throw IllegalStateException("Do not use `self` until initialized.")
}
private val inner = initializer()
}
fun <T> selfReference(initializer: SelfReference<T>.() -> T): T {
return SelfReference(initializer).self
}
It works, see this example:
class Holder(var x: Int = 0,
val action: () -> Unit)
val h: Holder = selfReference { Holder(0) { self.x++ } }
h.action()
h.action()
println(h.x) //2
But at this point the way in which initializer references the constructed value is self property.
And my question is: is there a way to rewrite SelfReference so that initializer is passed an argument (or a receiver) instead of using self property? This question can be reformulated to: is there a way to pass a lazily evaluated receiver/argument to a function or achieve this semantics some way?
What are the other ways to improve the code?
UPD: One possible way is to pass a function that returns self, thus it would be used as it() inside the initializer. Still looking for other ones.
The best I have managed to produce while still being completely generic is this:
class SelfReference<T>(val initializer: SelfReference<T>.() -> T) {
val self: T by lazy {
inner ?: throw IllegalStateException("Do not use `self` until initialized.")
}
private val inner = initializer()
operator fun invoke(): T = self
}
Adding the invoke operator lets you use it in the following way:
val h: Holder = selfReference { Holder(0) { this().x++ } }
This is the closest I got to make it look like something you would "normally" write.
Sadly I think it is not possible to get completely rid of a explicit access to the element. Since to do that you would need a lambda parameter of type T.() -> T but then you wouldn't be able to call that parameter without an instance of Tand being T a generic there is no clean and safe way to acquire this instance.
But maybe I'm wrong and this helps you think of a solution to the problem
is there a way to rewrite SelfReference so that initializer is passed an argument (or a receiver) instead of using self property? This question can be reformulated to: is there a way to pass a lazily evaluated receiver/argument to a function or achieve this semantics some way?
I'm not sure I completely understand your use case but this may be what you're looking for:
fun initHolder(x: Int = 0, holderAction: Holder.() -> Unit) : Holder {
var h: Holder? = null
h = Holder(x) { h!!.holderAction() }
return h
}
val h: Holder = initHolder(0) { x++ }
h.action()
h.action()
println(h.x) // 2
This works because holderAction is a lambda with a receiver (Holder.() -> Unit) giving the lambda access to the receiver's members.
This is a general solution since you may not be able to change the signature of the respective Holder constructor. It may be worth noting this solution does not require the class to be open, otherwise a similar approach could be done with a subclass using a secondary constructor.
I prefer this solution to creating a SelfReference class when there are only a few number of classes that need the change.
You may want to check for null instead of using !! in order to throw a helpful error. If Holder calls action in it's constructor or init block, you'll get a null pointer exception.
I'm pretty sure you can achieve the same results in a more readable and clear way using something like this:
fun <T> selfReferenced(initializer: () -> T) = initializer.invoke()
operator fun<T> T.getValue(any: Any?, property: KProperty<*>) = this
and later use
val valueName: ValueType by selfReferenced{
//here you can create and use the valueName object
}
Using as example your quoted question https://stackoverflow.com/a/35050722/2196460 you can do this:
val textToSpeech:TextToSpeech by selfReferenced {
TextToSpeech(
App.instance,
TextToSpeech.OnInitListener { status ->
if (status == TextToSpeech.SUCCESS) {
textToSpeech.setLanguage(Locale.UK)
}
})
}
Inside the selfReferenced block you can use the outer object with no restrictions. The only thing you should take care of, is declaring the type explicitly to avoid recursive type checking issues.

Conundrum with init() and dispatch_sync

In a class, I have the following init() function:
init() {
let q = 0
dispatch_sync(queue) {
self._state = State(q)
}
}
where _state is an instance of a struct State and queue a global dispatch queue.
I'm using the dispatch_sync call in order to synchronize the potentially concurrently accessed instance of the class.
I'm running in some weird issue, that the compiler is complaining about using the _state variable before it´s being initialized (namely using it in the block, before it is being initialized):
main.swift:363:37: error: variable 'self._state' used before being initialized
dispatch_sync(s_sync_queue) {
^
However, the sole purpose of using the dispatch queue and the block is to initialize the ivar.
The compiler even states, the code would return without initializing the variable _state:
main.swift:372:5: error: property 'self._state' not initialized
}
^
albeit, clearly, due to dispatch_sync the function init cannot return without leaving the variable _state uninitialized.
So, how could I solve the issue in an efficient manner?
One option is to declare _state as optional if you can.(If there is no harm to do that)
var _state:State?
if you make this optional you can use it in dispatch_sync.

Resources