Object lifetime management in Argentum. First look.

All nowadays programming languages fall in three possible categories on controlling object lifetimes, memory management and maintaining data structures:

  • Manual allocations and deallocations (C/C++...)
  • Garbage collector (Go, Kotlin, Java, Python, Dart...)
  • Semi-automatic ref counting (Swift, Rust, C++ with smart-pointers...)

All these three approaches have something in common.  They all allow developers to create a mess out of data structures and then try to assist programmers more or less in handling that mess.

Argentum  proposes the opposite approach. It allows programmers to explicitly declare ownership in cross-object references and automate all operations over data structures using these declarations. And these automatically provided operations in return guarantee that there are no dangling pointers, unsafe memory access or memory leaks.

Let's look at the these class declarations:

class Scene {
   // this field owns the Array, which owns its elements.
   elements = Array(SceneItem);

   //  this field just references an item, but doesn't own it.
   focused = &SceneItem;
}

class SceneItem {
   x = 0;
   y = 0;
   scene = &Scene;  // `scene` field references its scene, but doesn't own it.
}

class Label { +SceneItem;  // It's inheritance.
    text = "";

    // `style` field shares ownership over an immutable `Style` instance.
    style = *Style;
}

Our class diagram will be as follows

classDiagram class Scene{ +Array elements +SceneItem focused } class SceneItem { +int x +int y } class Label { +String text +Style style } class Style { +... } SceneItem <|-- Label

Let's create a number of instances of these classes:

// Create new mutable instance of Scene:
root = Scene;

// Create Style, fill it and freeze it (with *-operator), making it shareable:
normal = *Style.font(times).size(40).weight(600); 

// Create new Label instance and attach it to the scene.
root.elements.add(
    Label.at(10, 20).setText("Hello").setStyle(normal));

This code gives us a hierarchy of objects that are aware of their ownership and lifetimes.

classDiagram var_root *-- Scene Scene *-- Array Array *-- "*" Label Label o-- Style var_normal o-- Style

The Label exists as long as it is referenced from the root scene. Root scene exists as long as it's referenced by the root variable. The normal Style exists as long as it's referenced by either label or normal variable.

We can destroy all these objects by assigning new values to the correspondent variables and array items.

scene.elements.delete(0);
classDiagram var_root *-- Scene var_normal o-- Style Scene *-- Array

We can copy any object or the whole scene:

anotherScene = @root;  // @ - is a deep copy operator
classDiagram Scene *-- Array var_root *-- Scene var_normal o-- Style var_anotherScene *-- Scene_copy Scene_copy *-- Array_copy

 And this copy will preserve all the properties of the original scene:

  1. Scene and all mutable subitems will be copied and connected accordingly,
  2. All non-owning pointers:
    1. that are inner to the copied hierarchy will be copied in a way to preserve the topology graph,
    2. pointing outside will pointing to the same objects as in the original,
  1. If some objects hold system resources (files, sockets, fonts...) the special handlers will be called to handle these resources,
  2. Argentum also maintains the correctness of `parent` pointers.

And this copy operation performed at the cost of actual objects allocation with no overheads both in space and time.

The same is true for other operations: objects removal, freezing, passing between threads. All these operations are performed automatically by `*` and `&` markers on object fields.

Thus, this language is for sure works differently than mentioned above three groups of all existing languages

Leave a Reply

Your email address will not be published. Required fields are marked *