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.*/
}