[NO REPLY] Execution Context (rev #1, 2018-1-18)

A place of insane ideas, nothing to see here.
User avatar
Giovanni
Site Admin
Posts: 14444
Joined: Wed May 27, 2009 8:48 am
Location: Salerno, Italy
Has thanked: 1074 times
Been thanked: 921 times
Contact:

[NO REPLY] Execution Context (rev #1, 2018-1-18)

Postby Giovanni » Thu Jan 18, 2018 12:12 pm

From asynchronous functions it is not normally possible to modify global data. In order to be able to modify global variables it is required to switch to a specific "execution context" and then perform changes.

Defining an Execution Context

Code: Select all

cdef [abstract] [sync] [async <class1> [<class2> ... <classN>]] {
  int hidden_variable1;
  char hidden_variable2;
  static uint32_t hidden_variable3;
/* Following code sections are optional.*/
static_init:
  /* Only has access to hidden static variables.*/
  hidden_variable3 = (uint32_t)5;
/* Executed only if the context is entered from synchronous context.*/
sync_enter:
  ...
sync_leave:
  ...
/* Executed only if the context is entered from the **specified** asynchronous function class.*/
async_enter <class>:
  ...
async_leave <class>:
  ...
} <context>;


The abstract modifier makes the new context not usable directly, it can be used only as base context type from which other contexts can be derived:

Code: Select all

cdef base_context derived_context;


The async <class1>...<classN> modifier enables the use of the context from asynchronous functions of the specified classes.

The sync modifier enables the use of the context from synchronous context (plain C code).

Meaning of an Execution Context

An execution context is a mean to declare who is permitted to use marked variable/functions and to code rules for such variable/functions access.

From within an execution context:

- It is only possible to modify global variables marked with the context name.
- It is only possible to call functions marked with the context name or pure/const functions.

Derived Execution Contexts

Derived execution contexts work like normal execution contexts but can use variables and functions marked with the name of ancestor contexts. Ancestor contexts cannot use variables and functions of derived contexts.

Using an Execution Context

it is possible to switch to a context using the context statement:

Code: Select all

cdef async <isr> {
  ...
} my_context;

my_context int i = 0;

my_context void update(void) {
  ...
}

async <isr> void my_isr(void) {

  /* The asyncronous function is unable to access static variables, we can
     access "i" by switching to the appropriate execution context.*/
  context my_context {
    i++;
    update();
  }
}


Note that break and continue statements work as expected within a context block.

Nested Execution Contexts

It is not possible to nest execution contexts of the same type.

Code: Select all

context aaa {
  context aaa { /* Results in an error.*/
  }
}

aaa void func(void) {

  context aaa { /* Results in an error.*/
  }
}


Different execution contexts can be nested:

Code: Select all

context aaa {
  /* Only aaa variables/functions can be accessed.*/
  context bbb {
    /* Both aaa and bbb variables/functions can be accessed.*/
  }
  /* Only aaa variables/functions can be accessed.*/
}

aaa void func(void) {

  /* Only aaa variables/functions can be accessed.*/
  context bbb {
    /* Both aaa and bbb variables/functions can be accessed.*/
  }
  /* Only aaa variables/functions can be accessed.*/
}

Return to “Safer C”

Who is online

Users browsing this forum: No registered users and 7 guests