Up

module Netmcore_array

: sig

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, _) 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, _) 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, _) 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, _) 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, _) sarray -> int -> 'e

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

#
val length : (_, _) sarray -> int

Returns the length

#
val header : (_, 'h) sarray -> 'h

Returns the header

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

Returns the raw array in shared memory for unprotected access

#
val heap : (_, _) sarray -> 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 [root: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.)

end