Delete?

Concurnas provides a mechanism where by a local variable can be removed from scope via the del keyword. This has the additional side effect for non array Object types of invoking the delete method on them if one is defined. This is incredibly useful for performing resource management and is used in supporting the Concurnas gpu parallel computing as well as the off heap memory frameworks. Additionally Concurnas offers first class citizen support for the del keyword when applied to maps and lists.

Removing values from maps?

Values can be removed from a map as follows:

mymap = {taste -> 10}

del mymap['taste']//value corresponding to 'taste' is deleted

This saves us from having to write: mymap.remove('taste')

Removing values from lists?

Values can be removed from a list as follows:

mylist = [5, 34, 2, 5, 11]
del mylist[1]//the second value, '34', is removed from the list

This saves us from having to write: mylist.remove(1)

Deleting Objects?

Calling the delete operator on a variable in Concurnas does two things:

  1. The variable is removed from scope

  2. The delete method is called on the object pointed to by the variable

Here is an example of this in action:

deleteCalled = false
class DeleteMe{
  override delete() void => deleteCalled = true
}

todel = DeleteMe()
del todel
//todel is now out of scope and cannot be referenced
assert deleteCalled

Overriding the delete method as above will allows us to implement functionality to be invoked upon the del operator being applied to the object (or the delete method being called directly). For instance, closing or otherwise managing resources.

@DeleteOnUnusedReturn Annotation?

The @com.concurnas.lang.DeleteOnUnusedReturn annotation can be used to denote that the delete method should be invoked on the return value of a method or function if it is unused by the caller (i.e. popped off the stack). This affords a degree of flexibility in API design around objects which require resource management as one does not need to worry about the caller correctly dealing with a return value which they may to be optional. This is used heavily in the support for Concurnas parallel GPU computing framework and is useful with off heap memory management. For example:

from com.concurnas.lang import DeleteOnUnusedReturn

@DeleteOnUnusedReturn
class ClassWithResource{
  def delete(){
    //...
  }
}

def doWorkAndGetClassWithResouce(){
  ret = ClassWithResource()
  //do some work here
  ret
}

doWorkAndGetClassWithResouce()//the delete method on the returned ClassWithResource object will be called

In the above example the delete method will be called on the returned ClassWithResource object as it is unused by the caller. If it were used by the caller (e.g. assigned to a value, or used in as part of a nested method or function invocation) then the delete method will not be called.

Notes:

  1. The delete method will not be called if the returned object is null.

  2. If a method is decorated with @DeleteOnUnusedReturn then instances in all subclasses will also inherit this decoration.

  3. The annotation is not applied to refs to methods or functions which have been decorated with it.

Additionally, for refs which are returned from a function or method and are immediately extracted by the caller, these will also have the delete method called on the ref if the @DeleteOnUnusedReturn annotation is used. For example:

from com.concurnas.lang import DeleteOnUnusedReturn

@DeleteOnUnusedReturn
class ClassWithResource{
  def delete(){
    //...
  }
}

def doWorkAndGetClassWithResouce(){
  ret = ClassWithResource()
  //do some work here
  ret://returned as a local ref
}

got = doWorkAndGetClassWithResouce()//the delete method on the returned Local ref holding the ClassWithResource object will be called (but not on the ClassWithResource itself)