[f28fdee] | 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.
|
---|
[6e7b969] | 5 |
|
---|
| 6 | \section{Overloading and extern}
|
---|
| 7 | Cforall has overloading, allowing multiple definitions of the same name to
|
---|
[f28fdee] | 8 | be defined.~\cite{Moss18}
|
---|
[6e7b969] | 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:
|
---|
[f28fdee] | 16 | \begin{cfa}
|
---|
[6e7b969] | 17 | extern "C" {
|
---|
| 18 | ...
|
---|
| 19 | }
|
---|
[f28fdee] | 20 | \end{cfa}
|
---|
[6e7b969] | 21 |
|
---|
| 22 | To re-enable mangling once it is disabled the syntax is:
|
---|
[f28fdee] | 23 | \begin{cfa}
|
---|
[6e7b969] | 24 | extern "Cforall" {
|
---|
| 25 | ...
|
---|
| 26 | }
|
---|
[f28fdee] | 27 | \end{cfa}
|
---|
[6e7b969] | 28 |
|
---|
| 29 | Both should occur at the declaration level and effect all the declarations
|
---|
[f28fdee] | 30 | in @...@. Neither care about the state of mangling when they begin
|
---|
[6e7b969] | 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
|
---|
[f28fdee] | 36 | same syntax as pointers except they use ampersand (@&@) instead of
|
---|
| 37 | the asterisk (@*@). They can also be constaint or mutable, if they
|
---|
[6e7b969] | 38 | are mutable they may be assigned to by using the address-of operator
|
---|
[f28fdee] | 39 | (@&@) which converts them into a pointer.
|
---|
[6e7b969] | 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
|
---|
[f28fdee] | 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 | (@?++@).
|
---|
[6e7b969] | 51 |
|
---|
[f28fdee] | 52 | The special name for contructors is @?{}@, which comes from the
|
---|
[6e7b969] | 53 | initialization syntax in C. The special name for destructors is
|
---|
[f28fdee] | 54 | @^{}@. % I don't like the \^{} symbol but $^\wedge$ isn't better.
|
---|
[6e7b969] | 55 |
|
---|
| 56 | Any time a type T goes out of scope the destructor matching
|
---|
[f28fdee] | 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
|
---|
[6e7b969] | 59 | are usually omitted for optimization.
|
---|
| 60 |
|
---|
| 61 | \section{Polymorphism}
|
---|
| 62 | \CFA uses polymorphism to create functions and types that are defined over
|
---|
[f28fdee] | 63 | different types. \CFA polymorphic declarations serve the same role as \CC
|
---|
[6e7b969] | 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 |
|
---|
[f28fdee] | 70 | Forall clauses are written @forall( ... )@ where @...@ becomes
|
---|
[6e7b969] | 71 | the list of polymorphic variables (local type names) and assertions, which
|
---|
| 72 | repersent required operations on those types.
|
---|
| 73 |
|
---|
[f28fdee] | 74 | \begin{cfa}
|
---|
[6e7b969] | 75 | forall(dtype T | { void do_once(T &); })
|
---|
| 76 | void do_twice(T & value) {
|
---|
| 77 | do_once(value);
|
---|
| 78 | do_once(value);
|
---|
| 79 | }
|
---|
[f28fdee] | 80 | \end{cfa}
|
---|
[6e7b969] | 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 |
|
---|
[f28fdee] | 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}
|
---|
[6e7b969] | 91 | int quadruple(int x) {
|
---|
| 92 | void do_once(int & y) {
|
---|
| 93 | y = y * 2;
|
---|
| 94 | }
|
---|
| 95 | do_twice(x);
|
---|
| 96 | return x;
|
---|
| 97 | }
|
---|
[f28fdee] | 98 | \end{cfa}
|
---|
[6e7b969] | 99 | This is not the recommended way to implement a quadruple function but it
|
---|
[f28fdee] | 100 | does work. The complier will deduce that @do_twice@'s T is an
|
---|
[6e7b969] | 101 | integer from the argument. It will then look for a definition matching the
|
---|
[f28fdee] | 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
|
---|
[6e7b969] | 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.
|
---|
[f28fdee] | 109 | \begin{cfa}
|
---|
[6e7b969] | 110 | trait done_once(dtype T) {
|
---|
| 111 | void do_once(T &);
|
---|
| 112 | }
|
---|
[f28fdee] | 113 | \end{cfa}
|
---|
[6e7b969] | 114 |
|
---|
| 115 | After this the forall list in the previous example could instead be written
|
---|
| 116 | with the trait instead of the assertion itself.
|
---|
[f28fdee] | 117 | \begin{cfa}
|
---|
[6e7b969] | 118 | forall(dtype T | done_once(T))
|
---|
[f28fdee] | 119 | \end{cfa}
|
---|
[6e7b969] | 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 |
|
---|
[f28fdee] | 129 | \begin{cfa}
|
---|
[6e7b969] | 130 | forall(dtype T)
|
---|
| 131 | struct node {
|
---|
| 132 | node(T) * next;
|
---|
| 133 | T * data;
|
---|
| 134 | }
|
---|
[f28fdee] | 135 | \end{cfa}
|
---|
[6e7b969] | 136 |
|
---|
[f28fdee] | 137 | The @node(T)@ is a use of a polymorphic structure. Polymorphic types
|
---|
[6e7b969] | 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 |
|
---|
[f28fdee] | 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
|
---|
[6e7b969] | 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 |
|
---|
[f28fdee] | 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.
|
---|
[6e7b969] | 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.
|
---|
[f28fdee] | 166 | \begin{cfa}
|
---|
[6e7b969] | 167 | coroutine CountUp {
|
---|
| 168 | unsigned int next;
|
---|
| 169 | }
|
---|
[f28fdee] | 170 | \end{cfa}
|
---|
[6e7b969] | 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.
|
---|
[f28fdee] | 178 | \begin{cfa}
|
---|
[6e7b969] | 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 | }
|
---|
[f28fdee] | 187 | \end{cfa}
|
---|
[6e7b969] | 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
|
---|
[f28fdee] | 194 | expression: @resume(count).next@.
|
---|
[6e7b969] | 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 |
|
---|
[f28fdee] | 203 | Function parameters can have the @mutex@ qualifiers on reference
|
---|
| 204 | arguments, for example @void example(a_monitor & mutex arg);@. When the
|
---|
[6e7b969] | 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:
|
---|
[f28fdee] | 219 | \begin{cfa}
|
---|
[6e7b969] | 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 | }
|
---|
[f28fdee] | 230 | \end{cfa}
|
---|
[6e7b969] | 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
|
---|
[f28fdee] | 238 | destructor runs. Join also happens during the @join@ function which
|
---|
[6e7b969] | 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.
|
---|