# Module Netmcore_array

    module Netmcore_array: sig .. end

Shared arrays

This type of array is to some degree comparable with `Array`, but there are a few extensions:

- There is a so-called header. The header can have any type, and is typically used for managing concurrent access (e.g. mutexes). The header also lives in shared memory.
- The arrays can be grown in size

    type ('e, 'h) sarray

Arrays where the elements have type `'e` and the header has type `'h`

    type ('e, 'h) sarray_descr

The marshallable descriptor of a shared array

    val create : Netmcore.res_id -> 'e array -> 'h -> ('e, 'h) sarray

`create pool_id a h`: Creates a shared array by deeply copying a normal array `a` and using the copy of `h` as header

    val make : Netmcore.res_id -> int -> 'e -> 'h -> ('e, 'h) sarray

`make pool_id n x h`: Creates a shared array of the passed number of elements, copies the element `x`, and initializes each element of the new array with the single copy of `x`. The value `h` is copied and used as header.

    val init : Netmcore.res_id -> int -> (int -> 'e) -> 'h -> ('e, 'h) sarray

`init pool_id n f h`: Creates a shared array of the passed number of elements, and for getting the element at position `k` the function `f k` is run, and the copy of the result is written to the position. The header is set to the copy of `h`.

    val grow : ('e, 'a) sarray -> int -> 'e -> unit

`grow sa n x`: Grows the array to `n` elements. The new elements are initialized to a (single) copy of `x`.

If `n` is smaller than the current length, the function will do nothing, and keep the length.

    val set : ('e, 'a) sarray -> int -> 'e -> unit

`set sa k x`: Sets the `k-th` element of the array `sa` to a deep copy of `x`.

    val get_ro : ('e, 'a) sarray -> int -> 'e

`get_ro sa k`: Gets the `k`-th element of the shared array `sa`. Note that there is no guarantee that this value still exists if it is returned, and a parallely running `set` changes this element. If such values are accessed the program may crash!

    val get_p : ('e, 'b) sarray -> int -> ('e -> 'a) -> 'a

`get_p sa k f`: Gets the `k`-th element of the shared array `sa` and call `f` with this element, and returns the result of `f`. During the execution of `f` the requested element cannot be garbage collected.

    val get_c : ('e, 'a) sarray -> int -> 'e

`get_c sa k`: Gets a copy of the `k`-th element of the shared array `sæ`

    val length : ('a, 'b) sarray -> int

Returns the length

    val header : ('a, 'h) sarray -> 'h

Returns the header

    val deref : ('e, 'a) sarray -> 'e array

Returns the raw array in shared memory for unprotected access

    val heap : ('a, 'b) sarray -> Stdlib.Obj.t Netmcore_heap.heap

Return the backing heap structure

    val descr_of_sarray : ('e, 'h) sarray -> ('e, 'h) sarray_descr

Returns the descriptor

    val sarray_of_descr : Netmcore.res_id ->
           ('e, 'h) sarray_descr -> ('e, 'h) sarray

Look up the buffer for this descriptor

#### Mutating header fields

Special care has to be taken when mutating header fields. The header must completely live in the same heap. For adding new values, one has to use `Netmcore_heap.modify`. Example for a header of type:

        type header =
          { mutable n : int;
            mutable name : string
          }

Here, the field `n` can be directly assigned because an `int` is always an unboxed value. So,

        h.n <- new_value

is legal. However, strings are heap-allocated. For an assignment to `name` we need to use `Netmcore_heap.modify`, as in

        Netmcore_heap.modify
          (Netmcore_array.heap sa)
          (fun mutator ->
            h.name <- Netmcore_heap.add mutator new_value
          )

The function `Netmcore_heap.add` pushes a copy of the `new_value` to the heap, and this allows us to do the assignment.

During `Netcore_heap.modify` certain operations are prohibited because they would cause a deadlock:

- `grow`
- `set`
- `get_p`
- `get_c`

(This may be relaxed in a future version.)