Managing external memory in VASmalltalk

Whenever one has to deal with external libraries or API calls one has to create a memory structure in Smalltalk and set and gets information in this structure.

In general VASmalltalk can create references to memory in several ways:

* reference to a memory handled by the Smalltalk garbage collector
* reference to an external memory – allocated by external libraries
* reference to an external memory, allocated by the Smalltalk interpreter but not handled by the garbage collector.

For the following examples we look at the class OSPoint (Windows !), which is a subclass of OSStructure.This method handles two 4 byte-long signed integers. Therefore this structure consumes 8 bytes for each instance.

Reference to a memory handled by the Smalltalk garbage collector

You create an instance with the method „new“ or „new:“. Therefore to create an instance of that subclass offering memory for ONE structure element you execute:

OSPoint new

To create an instance offering memory for multiple structure elements one executes:

OSPoint new: x

where „x“ is the number of structures you want to store.

Instances of this type (which have an indirection level of 1, defined by the global constant „EsReftypeStruct“ – have a look at the instance creation methods „new“) are located within the memory handled by the garbage collector.
The memory itself is created using an instance of ByteArray, which IS the memory container holding the structure information.
Due to the fact, that its a ordinary Smalltalk object, VA is allowed to move the object within the global memory.

The advantage of these instances is, that they are garbage collected by Smalltalk and you do not have to think about them any more.

If you use an instance like this as a parameter in an API-call, one has to consider two different situations:

The simplest way is to call the API in a synchronous way. Then – during the call – Smalltalk is waiting for a return of the API call and the garbage collector can not work. The pointer – given to the API function – points to the first byte of the ByteArray.

Asynchronous calling is also not difficult. The documentation does not say anything about that – but it seems to be, that VASmalltalk copies the parameter (it’s after all an instance of ByteArray and Smalltalk can queries its size) to fixed memory, does the call and after returning copies the value back into the original object.

This method can be used, whenever it is clear, that the pointer is NOT used AFTER the actual API call.

Reference to a non-Smalltalk memory handled by external libraries

Here the structure is located within the memory managed by the dynamic library you just called – and a Api call returned an integer representing the address of the memory, where the structure is located.

To get access via a Smalltalk object you may execute:

OSPoint address: x

where „x“ is the integer (uint32 – address). This object has an indirection level of 2 (represented by the constant „EsReftypePointer“). It shows to a non-Smalltalk memory. Therefore Smalltalk also does not know, how much memory had been located at that location and the debugger only shows the address – nothing more.

The problem in this situation is always the same: who has the responsibility for the memory ? Who has to free them and HOW is this memory released. The documentation of the dynamic library must mention this problem.

Reference to a non-Smalltalk memory handled by Smalltalk

Whenever you need a structure, which contents must be used AFTER an API call has been finished, you must allocate memory in non-Smalltalk memory. You do this via

OSPoint calloc

To create an instance offering memory for multiple structure elements one executes:

OSPoint calloc: x

The same way as mentioned above with „new“, „new:“.

The problem here is, that you as the programmer has to manage now memory manually – the same way as a normal C developer must do. Though you have a Smalltalk object to access the non-Smalltalk memory, the memory is NOT released when the object is released !!!! There is not automatically finalization.

Accessing the members of OSStructure

Adding your primitive structure as a subclass of OSStructure gives you two advantages:

you can define the behaviour of ONE single element (access to the members of this element)
you have array based accessing possibility

For each member you have to write accessing (reading and writing) methods using methods like „#int32At:“, „float64At:“.

The array-based access is defined by the methods „#at:“ and „#at:put:“

If I have a single instance of OSPoint (holding ONE structure element) you may write either

anOSPoint x

but also:

(anOSPoint at: 0) x

Here the one-based index mechanism of Smalltalk is NOT right. The index is starting with „0“ !

Another problem is, that the method „#at:“ always COPIES the content of the structure element. That means, that

anOSPoint x: 12

is NOT equal to

(anOSPoint at: 0) x: 12

Normally nobody would do that when you have only ONE element stored. But what about having an array of structure elements ? Then one has to write something like „(anOSPoint at: index) memberAccessor“.

But to change the value one must write:

(anOSPoint at: index) put: ((anOSPoint at: index) x: 12)

The advantage of this lousy statement is, that it works with memory located either with „calloc:“ or „new:“

This entry was posted in Smalltalk. Bookmark the permalink.

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s