Skip to content

Commit b95d5ff

Browse files
authored
Merge branch 'main' into target-file-property
2 parents 2b79424 + 8d704c3 commit b95d5ff

File tree

3 files changed

+39
-11
lines changed

3 files changed

+39
-11
lines changed

docs/developer/downloading-and-building.mdx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
---
2-
title: Developer Setup
3-
description: Setting up Lingua Franca for developers.
2+
title: Building from Source Code
3+
description: Instruction for downloading and building the Lingua Franca source code.
44
---
55

66
## Prerequisites

docs/installation.md

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -149,6 +149,4 @@ Regular and nightly release builds of the command line tools can be downloaded f
149149

150150
### From Source
151151

152-
Please refer to the [Lingua Franca GitHub repository](https://github.com/lf-lang/lingua-franca) for build instructions.
153-
154-
If you'd like to contribute to Lingua Franca, you can find details about the recommended developer setup here.
152+
If you would like to build from source or contribute to Lingua Franca, you can find further instructions in the [developer section](./developer/downloading-and-building.mdx).

docs/reference/target-language-details.mdx

Lines changed: 36 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1118,12 +1118,6 @@ reactor Source {
11181118

11191119
The first reaction specifies the destructor and copy constructor (the latter of which will be used if any downstream reactor has a mutable input or wishes to make a writable copy).
11201120

1121-
**IMPORTANT:** The array constructed should be sent to only one output port using `lf_set`. If you need to send it to more than one output port or to use it as the payload of an action, you should use `lf_set_token`.
1122-
1123-
:::warning
1124-
**FIXME:** Show how to do this.
1125-
:::
1126-
11271121
A reactor receiving this array is straightforward. It just references the array elements as usual in C, as illustrated by this example:
11281122

11291123
```lf-c
@@ -1142,6 +1136,10 @@ reactor Print() {
11421136

11431137
The deallocation of memory for the data will occur automatically after the last reactor that receives a pointer to the data has finished using it, using the destructor specified by `lf_set_destructor` or `free` if none specified.
11441138

1139+
Sometimes, it is not necessary to explicitly provide a destructor or copy constructor for a data type.
1140+
Suppose your output port has type `foo*` for some data type `foo`.
1141+
If the dynamically allocated memory pointed to has size `sizeof(foo)` and resides in contiguous memory, then the default destructor and copy constructor will suffice.
1142+
11451143
Occasionally, you will want an input or output type to be a pointer, but you don't want the automatic memory allocation and deallocation. A simple example is a string type, which in C is `char*`. Consider the following (erroneous) reactor:
11461144

11471145
```lf-c
@@ -1186,6 +1184,38 @@ reactor SendsPointer {
11861184

11871185
The above technique can be used to abuse the reactor model of computation by communicating pointers to shared variables. This is generally a bad idea unless those shared variables are immutable. The result will likely be nondeterministic. Also, communicating pointers across machines that do not share memory will not work at all.
11881186

1187+
Finally, sometimes, you will want to use the same dynamically allocated data structure for multiple purposes over time.
1188+
In this case, you can explicitly create a token to carry the data, and the token mechanism will take care of reference counting and freeing the allocated memory only after all users are done with it.
1189+
For example, suppose that your reaction wishes to produce an output and schedule an action with the same payload.
1190+
This can be accomplished as follows:
1191+
1192+
```lf-c
1193+
reactor TokenSource2 {
1194+
output out: int_array_t*
1195+
state count: int = 0
1196+
timer t(0, 2 ms)
1197+
logical action a(1 ms): int_array_t*
1198+
1199+
reaction(startup) -> out {=
1200+
lf_set_destructor(out, int_array_destructor);
1201+
lf_set_copy_constructor(out, int_array_copy_constructor);
1202+
=}
1203+
1204+
reaction(t, a) -> out, a {=
1205+
int_array_t* array = int_array_constructor(3);
1206+
for (size_t i = 0; i < array->length; i++) {
1207+
array->data[i] = self->count++;
1208+
}
1209+
lf_token_t* token = lf_new_token((lf_port_base_t*)out, array, 1);
1210+
lf_set_token(out, token);
1211+
lf_schedule_token(a, 0, token);
1212+
=}
1213+
}
1214+
```
1215+
1216+
The call to `lf_new_token` creates a token with the `int_array_t` struct as its payload (technically, it creates a token with an array of length 1, where the one element is the dynamically allocated array).
1217+
The cast in `(lf_port_base_t*)out` is necessary to suppress warnings because C does not support inheritance.
1218+
11891219
### Mutable Inputs
11901220

11911221
Although it cannot be enforced in C, a receiving reactor should not modify the values provided by an input. Inputs are logically _immutable_ because there may be several recipients. Any recipient that wishes to modify the input should make a copy of it. Fortunately, a utility is provided for this pattern. Consider the [ArrayScale](https://github.com/lf-lang/lingua-franca/blob/master/test/C/src/ArrayScale.lf) example, here modified to use the above `int_array_t` data type:

0 commit comments

Comments
 (0)