1 | \chapter{\CFA Existing Features} |
---|
2 | |
---|
3 | \CFA (C-for-all)~\cite{Cforall} is an open-source project extending ISO C with modern safety and productivity features, while still ensuring backwards compatibility with C and its programmers. |
---|
4 | \CFA is designed to have an orthogonal feature-set based closely on the C programming paradigm (non-object-oriented) and these features can be added incrementally to an existing C code-base allowing programmers to learn \CFA on an as-needed basis. |
---|
5 | |
---|
6 | \section{Overloading and extern} |
---|
7 | Cforall has overloading, allowing multiple definitions of the same name to |
---|
8 | be defined.~\cite{Moss18} |
---|
9 | |
---|
10 | This also adds name mangling so that the assembly symbols are unique for |
---|
11 | different overloads. For compatability with names in C there is also a |
---|
12 | syntax to diable the name mangling. These unmangled names cannot be overloaded |
---|
13 | but act as the interface between C and \CFA code. |
---|
14 | |
---|
15 | The syntax for disabling mangling is: |
---|
16 | \begin{cfa} |
---|
17 | extern "C" { |
---|
18 | ... |
---|
19 | } |
---|
20 | \end{cfa} |
---|
21 | |
---|
22 | To re-enable mangling once it is disabled the syntax is: |
---|
23 | \begin{cfa} |
---|
24 | extern "Cforall" { |
---|
25 | ... |
---|
26 | } |
---|
27 | \end{cfa} |
---|
28 | |
---|
29 | Both should occur at the declaration level and effect all the declarations |
---|
30 | in @...@. Neither care about the state of mangling when they begin |
---|
31 | and will return to that state after the group is finished. So re-enabling |
---|
32 | is only used to nest areas of mangled and unmangled declarations. |
---|
33 | |
---|
34 | \section{References} |
---|
35 | \CFA adds references to C. These are auto-dereferencing pointers and use the |
---|
36 | same syntax as pointers except they use ampersand (@&@) instead of |
---|
37 | the asterisk (@*@). They can also be constaint or mutable, if they |
---|
38 | are mutable they may be assigned to by using the address-of operator |
---|
39 | (@&@) which converts them into a pointer. |
---|
40 | |
---|
41 | \section{Constructors and Destructors} |
---|
42 | |
---|
43 | Both constructors and destructors are operators, which means they are just |
---|
44 | functions with special names. The special names are used to define them and |
---|
45 | may be used to call the functions expicately. The \CFA special names are |
---|
46 | constructed by taking the tokens in the operators and putting @?@ where |
---|
47 | the arguments would go. So multiplication is @?*?@ while dereference |
---|
48 | is @*?@. This also make it easy to tell the difference between |
---|
49 | pre-fix operations (such as @++?@) and post-fix operations |
---|
50 | (@?++@). |
---|
51 | |
---|
52 | The special name for contructors is @?{}@, which comes from the |
---|
53 | initialization syntax in C. The special name for destructors is |
---|
54 | @^{}@. % I don't like the \^{} symbol but $^\wedge$ isn't better. |
---|
55 | |
---|
56 | Any time a type T goes out of scope the destructor matching |
---|
57 | @void ^?{}(T &);@ is called. In theory this is also true of |
---|
58 | primitive types such as @int@, but in practice those are no-ops and |
---|
59 | are usually omitted for optimization. |
---|
60 | |
---|
61 | \section{Polymorphism} |
---|
62 | \CFA uses polymorphism to create functions and types that are defined over |
---|
63 | different types. \CFA polymorphic declarations serve the same role as \CC |
---|
64 | templates or Java generics. |
---|
65 | |
---|
66 | Polymorphic declaractions start with a forall clause that goes before the |
---|
67 | standard (monomorphic) declaration. These declarations have the same syntax |
---|
68 | except that you may use the names introduced by the forall clause in them. |
---|
69 | |
---|
70 | Forall clauses are written @forall( ... )@ where @...@ becomes |
---|
71 | the list of polymorphic variables (local type names) and assertions, which |
---|
72 | repersent required operations on those types. |
---|
73 | |
---|
74 | \begin{cfa} |
---|
75 | forall(dtype T | { void do_once(T &); }) |
---|
76 | void do_twice(T & value) { |
---|
77 | do_once(value); |
---|
78 | do_once(value); |
---|
79 | } |
---|
80 | \end{cfa} |
---|
81 | |
---|
82 | A polymorphic function can be used in the same way normal functions are. |
---|
83 | The polymorphics variables are filled in with concrete types and the |
---|
84 | assertions are checked. An assertion checked by seeing if that name of that |
---|
85 | type (with all the variables replaced with the concrete types) is defined at |
---|
86 | the the call site. |
---|
87 | |
---|
88 | As an example, even if no function named @do_once@ is not defined |
---|
89 | near the definition of @do_twice@ the following code will work. |
---|
90 | \begin{cfa} |
---|
91 | int quadruple(int x) { |
---|
92 | void do_once(int & y) { |
---|
93 | y = y * 2; |
---|
94 | } |
---|
95 | do_twice(x); |
---|
96 | return x; |
---|
97 | } |
---|
98 | \end{cfa} |
---|
99 | This is not the recommended way to implement a quadruple function but it |
---|
100 | does work. The complier will deduce that @do_twice@'s T is an |
---|
101 | integer from the argument. It will then look for a definition matching the |
---|
102 | assertion which is the @do_once@ defined within the function. That |
---|
103 | function will be passed in as a function pointer to @do_twice@ and |
---|
104 | called within it. |
---|
105 | |
---|
106 | To avoid typing out long lists of assertions again and again there are also |
---|
107 | traits which collect assertions into convenent packages that can then be used |
---|
108 | in assertion lists instead of all of their components. |
---|
109 | \begin{cfa} |
---|
110 | trait done_once(dtype T) { |
---|
111 | void do_once(T &); |
---|
112 | } |
---|
113 | \end{cfa} |
---|
114 | |
---|
115 | After this the forall list in the previous example could instead be written |
---|
116 | with the trait instead of the assertion itself. |
---|
117 | \begin{cfa} |
---|
118 | forall(dtype T | done_once(T)) |
---|
119 | \end{cfa} |
---|
120 | |
---|
121 | Traits can have arbitrary number of assertions in them and are usually used to |
---|
122 | create short hands for, and give descriptive names to, commond groupings of |
---|
123 | assertions. |
---|
124 | |
---|
125 | Polymorphic structures and unions may also be defined by putting a forall |
---|
126 | clause before the declaration. The type variables work the same way except |
---|
127 | are now used in field declaractions instead of parameters and local variables. |
---|
128 | |
---|
129 | \begin{cfa} |
---|
130 | forall(dtype T) |
---|
131 | struct node { |
---|
132 | node(T) * next; |
---|
133 | T * data; |
---|
134 | } |
---|
135 | \end{cfa} |
---|
136 | |
---|
137 | The @node(T)@ is a use of a polymorphic structure. Polymorphic types |
---|
138 | must be provided their polymorphic parameters. |
---|
139 | |
---|
140 | There are many other features of polymorphism that have not given here but |
---|
141 | these are the ones used by the exception system. |
---|
142 | |
---|
143 | \section{Concurrency} |
---|
144 | |
---|
145 | \CFA has a number of concurrency features, @thread@s, |
---|
146 | @monitor@s and @mutex@ parameters, @coroutine@s and |
---|
147 | @generator@s. The two features that interact with the exception system |
---|
148 | are @thread@s and @coroutine@s; they and their supporting |
---|
149 | constructs will be described here. |
---|
150 | |
---|
151 | \subsection{Coroutines} |
---|
152 | Coroutines are routines that do not have to finish execution to hand control |
---|
153 | back to their caller, instead they may suspend their execution at any time |
---|
154 | and resume it later. |
---|
155 | Coroutines are not true concurrency but share some similarities and many of |
---|
156 | the same underpinnings and so are included as part of the \CFA threading |
---|
157 | library. |
---|
158 | |
---|
159 | In \CFA coroutines are created using the @coroutine@ keyword which |
---|
160 | works just like @struct@ except that the created structure will be |
---|
161 | modified by the compiler to satify the @is_coroutine@ trait. |
---|
162 | |
---|
163 | These structures act as the interface between callers and the coroutine, |
---|
164 | the fields are used to pass information in and out. Here is a simple example |
---|
165 | where the single field is used to pass the next number in a sequence out. |
---|
166 | \begin{cfa} |
---|
167 | coroutine CountUp { |
---|
168 | unsigned int next; |
---|
169 | } |
---|
170 | \end{cfa} |
---|
171 | |
---|
172 | The routine part of the coroutine is a main function for the coroutine. It |
---|
173 | takes a reference to a coroutine object and returns nothing. In this function, |
---|
174 | and any functions called by this function, the suspend statement may be used |
---|
175 | to return execution to the coroutine's caller. When control returns to the |
---|
176 | function it continue from that same suspend statement instead of at the top |
---|
177 | of the function. |
---|
178 | \begin{cfa} |
---|
179 | void main(CountUp & this) { |
---|
180 | unsigned int next = 0; |
---|
181 | while (true) { |
---|
182 | this.next = next; |
---|
183 | suspend; |
---|
184 | next = next + 1; |
---|
185 | } |
---|
186 | } |
---|
187 | \end{cfa} |
---|
188 | |
---|
189 | Control is passed to the coroutine with the resume function. This includes the |
---|
190 | first time when the coroutine is starting up. The resume function takes a |
---|
191 | reference to the coroutine structure and returns the same reference. The |
---|
192 | return value is for easy access to communication variables. For example the |
---|
193 | next value from a count-up can be generated and collected in a single |
---|
194 | expression: @resume(count).next@. |
---|
195 | |
---|
196 | \subsection{Monitors and Mutex} |
---|
197 | |
---|
198 | True concurrency does not garrenty ordering. To get some of that ordering back |
---|
199 | \CFA uses monitors and mutex (mutual exclution) parameters. A monitor is |
---|
200 | another special declaration that contains a lock and is compatable with mutex |
---|
201 | parameters. |
---|
202 | |
---|
203 | Function parameters can have the @mutex@ qualifiers on reference |
---|
204 | arguments, for example @void example(a_monitor & mutex arg);@. When the |
---|
205 | function is called it will acquire the lock on all of the mutex parameters. |
---|
206 | |
---|
207 | This means that all functions that mutex on a type are part of a critical |
---|
208 | section and only one will ever run at a time. |
---|
209 | |
---|
210 | \subsection{Threads} |
---|
211 | While coroutines allow new things to be done with a single execution path |
---|
212 | threads actually introduce new paths of execution that continue independently. |
---|
213 | Now for threads to work together their must be some communication between them |
---|
214 | and that means the timing of certain operations does have to be known. There |
---|
215 | or various means of syncronization and mutual exclution provided by \CFA but |
---|
216 | for exceptions only the basic two -- fork and join -- are needed. |
---|
217 | |
---|
218 | Threads are created like coroutines except the keyword is changed: |
---|
219 | \begin{cfa} |
---|
220 | thread StringWorker { |
---|
221 | const char * input; |
---|
222 | int result; |
---|
223 | }; |
---|
224 | |
---|
225 | void main(StringWorker & this) { |
---|
226 | const char * localCopy = this.input; |
---|
227 | // ... do some work, perhaps hashing the string ... |
---|
228 | this.result = result; |
---|
229 | } |
---|
230 | \end{cfa} |
---|
231 | The main function will start executing after the fork operation and continue |
---|
232 | executing until it is finished. If another thread joins with this one it will |
---|
233 | wait until main has completed execution. In other words everything the thread |
---|
234 | does is between fork and join. |
---|
235 | |
---|
236 | From the outside this is the creation and destruction of the thread object. |
---|
237 | Fork happens after the constructor is run and join happens before the |
---|
238 | destructor runs. Join also happens during the @join@ function which |
---|
239 | can be used to join a thread earlier. If it is used the destructor does not |
---|
240 | join as that has already been completed. |
---|