How to pass a value to a method in an isolated object in Ballerina?

51 views Asked by At

I have an implementation of a queue in Ballerina that is supposed to work in a concurrency environment as shown below. However, it generates the error invalid attempt to transfer a value into a 'lock' statement with restricted variable usage. What is the optimal way to solve this?

type Element record {|
    int id;
    string name;
|};

isolated class Queue {
    private Element[] Elements = [];

    function push(Element element) {
        lock {
            self.Elements.push(element);
        }
    }
}
1

There are 1 answers

0
Nipuna Fernando On BEST ANSWER

The above scenario violates the isolated root invariant (i.e., any mutable state accessible via the isolated root is only accessible via the isolated root) since you are passing a mutable data (element) to an isolated object (Queue). Since the passing value is mutable, it is difficult to guarantee safety for the isolated object as its state can be manipulated from outside of the isolated object, such as by the calling function.

For the above scenario, there are two solutions that can be chosen based on additional constraints that may be applied to the program. In both solutions, the end goal is to decouple the access to the elements of the array from outside the isolated object.

Solution 1: Make the parameter immutable

If you have the capability to refactor the function definition, you can ensure the parameters to be immutable by intersecting the arguments with the readonly type. Since the parameter is now immutable, we can guarantee that it cannot be manipulated from outside the isolated object.

function push(Element & readonly element) {
    lock {
        self.Elements.push(element);
    }
}

Solution 2: Clone the parameter within the lock

Within the lock statement, we can clone the parameter so that the isolated object can obtain a copy that cannot be disrupted from outside the isolated object. This is only feasible since Element is a subtype of anydata which has the functionality to clone the given value.

function push(Element element) {
    lock {
        Element clonedElement = element.clone();
        self.Elements.push(clonedElement);
    }
}