1. Interface conventions

This document describes the conventions used in the programming interface to the Memory Pool System. It also contains our policy for support for the public identifiers and definitions of general types that appear throughout the interface.

1.1. Support policy

  1. We support the documented behaviour of public symbols in the MPS interface. We will only remove these symbols or change their behaviour in a new version, and not in a patch release. Normally we will give one version’s notice before removing a symbol or changing a particular documented behaviour: that is, there will be a version in which the symbol (or reliance on some of its behaviour) is deprecated.

    Note

    If you are relying on a feature and you see that it’s deprecated, please contact us. It makes a difference if we know that someone is using a feature.

  2. Behaviour that is not documented in the Guide, Reference, or Pool reference is not supported and may change without notice in future releases. In particular, private identifiers may disappear or their behaviour be changed without notice in future releases.

1.2. Language

  1. The MPS public interface conforms to ANSI/ISO Standard C (IEC 9899:1990).

1.3. Headers

  1. The main interface is in the header mps.h. This header contains all the core MPS interfaces. In practice, you always need at least one arena class and one pool class header file as well.
  2. We will always prefix public header file names with mps to avoid clashes. We reserve the right to create new headers with names beginning with mps in future versions.
  3. Pool class headers have names beginning with mpsc. For example, the header for AMC (Automatic Mostly-Copying) is mpscamc.h.
  4. Arena class headers have names beginning with mpsa. For example, the header for the virtual memory arena class is mpsavm.h.

1.4. Identifiers

  1. Identifiers are in lower case, except for preprocessor constants and macros that do not behave like functions, which are in upper case. Words are joined by underscores.
  2. All identifiers are either public or private.
  3. The names of public types, functions, variables, and macros start with mps_ or MPS_. The names of public structure members start with any letter.
  4. Private identifiers start with an underscore _.
  5. Type names end with _t, except for structure and union types.
  6. The names of structure types and tags end with _s.
  7. The names of union types and tags end with _u.

1.5. Types

There are three kinds of types declared in the MPS interface: transparent types, opaque types, and derived types.

  1. A transparent type is an alias defined using typedef, and this is documented so that the client program can rely on that fact. For example, mps_addr_t is a transparent alias for void *. Transparent types express intentions in the interface: in the case of mps_addr_t it represents a pointer that is under the control of the MPS.

  2. An opaque type is a pointer to an incomplete structure type. The client program must not rely on details of its implementation. For example, the type mps_arena_t is an alias for struct mps_arena_s *, but the implementation of struct mps_arena_s is not public.

    There are a few structure types that are declared in mps.h but whose implementation is not public. These only exist so that code can be inlined using macros. The most important of these is the scan state structure mps_ss_s, which is accessed by scanning macros such as MPS_SCAN_BEGIN() and MPS_FIX12().

  3. A derived type is a structure or function type based on transparent and opaque types and on built-in C types. The degree to which you may or must depend upon the implementation of a derived type is covered by the documentation for the type. For example, the structure type mps_ap_s has a mixture of public and private members.

1.6. Functions

  1. Operations that might fail return a result code, rather than a “special value” of the return type. See Error handing.
  2. A function that needs to return a value as well as a result code returns the value via an out parameter, a parameter that points to a location to store the result.
  3. A function that stores a result in the location pointed to by an out parameter only does so if the function is successful (that is, if the function returns MPS_RES_OK).
  4. The value in the location pointed to by an out parameter is not read by the function.
  5. Out parameters have names ending with _o.
  6. A function that both needs to read a value stored in a location and update the value does so via an in/out parameter, which is the same as an out parameter except that the location it points to is read by the function. See for example MPS_FIX12().
  7. In/out parameters have names ending with _io.
  8. A function that takes optional arguments does so in the form of an array of keyword argument structures. These functions have names ending with _k. See Keyword arguments.

1.7. Type punning

It’s tempting to use a type cast to change the type of an in/out or out parameter, like this:

/* allocate a struct foo */
struct foo *fp;
res = mps_alloc((mps_addr_t *)&fp, pool, sizeof(struct foo));

This is known as type punning, and its behaviour is not defined in ANSI/ISO Standard C. See ISO/IEC 9899:1990 §6.3.2.3, which defines the conversion of a pointer from one type to another: the behaviour of this cast is not covered by any of the cases in the standard.

Instead, we recommend this approach:

mps_addr_t p;
struct foo *fp;
res = mps_alloc(&p, pool, sizeof(struct foo));
if(res) /* handle error case */;
fp = (struct foo *)p;

This is portable because conversion from void * to any other object pointer type is defined by ISO/IEC 9899:1990 §6.3.2.3.1.

1.8. Macros

  1. For function-like macros, the MPS follows the same convention as the Standard C library. To quote ISO/IEC 9899:1990 §7.1.7:

    Any function declared in a header may additionally be implemented as a macro defined in the header, so a library function should not be declared explicitly if its header is included. Any macro definition of a function can be suppressed locally be enclosing the name of the function in parentheses, because the name is then not followed by the left parenthesis that indicates expansion of a macro function name. [...] Any invocation of a library function that is implemented as a macro shall expand to code that evaluates each of its arguments exactly once, fully protected by parentheses where necessary, so it is generally safe to use arbitrary expressions as arguments.

  2. Some function-like macros evaluate an argument more than once, so it is not safe to have a side effect in an argument of such a method. These special cases are documented. For example, mps_reserve().

  3. If you need the function rather than the macro, there are two approaches. You can undefine the macro:

    #undef mps_reserve
    res = mps_reserve(...);  /* calls function */
    

    Or you can put the name in parentheses:

    res = (mps_reserve)(...);  /* calls function */
    
  4. Statement-like macros have names in uppercase, for example MPS_RESERVE_BLOCK(). These macros behave like statements rather than expressions, so that you cannot write:

    (MPS_RESERVE_BLOCK(res, p, ap, size), 0)
    
  5. Details of the macro expansion, although visible in the header file, are not part of the MPS interface, and might change between releases. Don’t rely on them, unless they are documented separately.

1.9. General types

mps_addr_t

The type of addresses managed by the MPS, and also the type of references.

It is a transparent alias for void *.

It is used in the MPS interface for any pointer that is under the control of the MPS. In accordance with standard C practice, null pointers of type mps_addr_t will never be used to represent a reference to a block.

mps_align_t

The type of an alignment.

It is a transparent alias for size_t.

An alignment must be a positive power of 2.

mps_bool_t

The type of a Boolean value.

It is a transparent alias for int.

When used as an input parameter to the MPS, a value of 0 means “false” and any other value means “true”. As an output parameter or function return from the MPS, 0 means “false”, and 1 means “true”.

mps_clock_t

The type of a processor time.

It is a transparent alias for mps_word_t.

This is the type returned by the plinth function mps_clock().

mps_label_t

The type of a telemetry label.

It is an unsigned integral type.

mps_word_t

An unsigned integral type that is the same size as an object pointer, so that sizeof(mps_word_t) == sizeof(void *).

The exact identity of this type is platform-dependent. Typical identities are unsigned long and unsigned __int_64.

Topic

Platforms.