Changeset c1ea11b
- Timestamp:
- Jun 24, 2019, 11:12:01 AM (6 years ago)
- Branches:
- ADT, arm-eh, ast-experimental, enum, forall-pointer-decay, jacob/cs343-translation, jenkins-sandbox, master, new-ast, new-ast-unique-expr, pthread-emulation, qualifiedEnum
- Children:
- b58affe7, c1398e4
- Parents:
- 18e683b (diff), 9e0a360 (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the(diff)
links above to see all the changes relative to each parent. - Files:
-
- 4 added
- 49 edited
Legend:
- Unmodified
- Added
- Removed
-
benchmark/Makefile.am
r18e683b rc1ea11b 11 11 ## Created On : Sun May 31 09:08:15 2015 12 12 ## Last Modified By : Peter A. Buhr 13 ## Last Modified On : Tue Nov 6 09:01:23 201814 ## Update Count : 2613 ## Last Modified On : Sun Jun 23 12:34:29 2019 14 ## Update Count : 52 15 15 ############################################################################### 16 16 … … 21 21 include $(top_srcdir)/src/cfa.make 22 22 23 AM_CFLAGS = -O2 -Wall -Wextra - Werror -I$(srcdir) -lrt -pthread23 AM_CFLAGS = -O2 -Wall -Wextra -I$(srcdir) -lrt -pthread # -Werror 24 24 AM_CFAFLAGS = -quiet -nodebug -in-tree 25 25 AM_UPPFLAGS = -quiet -nodebug -multi -std=c++14 … … 31 31 BENCH_V_JAVAC = $(__bench_v_JAVAC_$(__quiet)) 32 32 BENCH_V_UPP = $(__bench_v_UPP_$(__quiet)) 33 BENCH_V_QTHREAD = $(__bench_v_QTHREAD_$(__quiet)) 33 34 34 35 __quiet = verbose … … 45 46 __bench_v_JAVAC_verbose = $(AM_V_JAVAC) 46 47 __bench_v_UPP_verbose = $(AM_V_UPP) 47 48 __bench_v_QTHREAD_verbose = $(AM_V_CC) 48 49 49 50 … … 51 52 REPEAT = ${abs_top_builddir}/tools/repeat 52 53 STATS = ${abs_top_srcdir}/tools/stat.py 53 repeats = 3 054 repeats = 3 # 30 54 55 skipcompile = no 55 56 TIME_FORMAT = "%E" … … 124 125 125 126 ctxswitch.csv: 126 @echo "coroutine,thread" > $@ 127 @echo "generator,coroutine,thread" > $@ 128 @+make ctxswitch-cfa_generator.runquiet >> $@ && echo -n ',' >> $@ 127 129 @+make ctxswitch-cfa_coroutine.runquiet >> $@ && echo -n ',' >> $@ 128 130 @+make ctxswitch-cfa_thread.runquiet >> $@ … … 153 155 $(BENCH_V_CC)$(COMPILE) -DBENCH_N=500000000 $(srcdir)/fetch_add.c 154 156 157 ttst_lock$(EXEEXT): 158 $(BENCH_V_CC)$(COMPILE) -DBENCH_N=500000000 $(srcdir)/ttst_lock.c 159 155 160 tls-fetch_add$(EXEEXT): 156 161 $(BENCH_V_CC)$(COMPILE) -DBENCH_N=500000000 $(srcdir)/tls-fetch_add.c … … 161 166 function.run \ 162 167 fetch_add.run \ 168 ttst_lock.run \ 163 169 tls-fetch_add.run \ 164 170 ctxswitch-pthread.run \ 171 ctxswitch-cfa_generator.run \ 165 172 ctxswitch-cfa_coroutine.run \ 166 173 ctxswitch-cfa_thread.run \ … … 169 176 ctxswitch-upp_thread.run \ 170 177 ctxswitch-goroutine.run \ 171 ctxswitch-java_thread.run 178 ctxswitch-java_thread.run \ 179 ctxswitch-qthreads.run 180 172 181 173 182 if WITH_LIBFIBRE … … 188 197 ctxswitch-pthread$(EXEEXT): 189 198 $(BENCH_V_CC)$(COMPILE) -DBENCH_N=50000000 $(srcdir)/ctxswitch/pthreads.c 199 200 ctxswitch-cfa_generator$(EXEEXT): 201 $(BENCH_V_CFA)$(CFACOMPILE) -DBENCH_N=50000000 $(srcdir)/ctxswitch/cfa_gen.cfa 190 202 191 203 ctxswitch-cfa_coroutine$(EXEEXT): … … 212 224 @echo "java JavaThread" >> a.out 213 225 @chmod a+x a.out 226 227 ctxswitch-qthreads$(EXEEXT): 228 $(BENCH_V_QTHREADS)$(COMPILE) -DBENCH_N=50000000 -I/u/pabuhr/software/qthreads/include -L/u/pabuhr/software/qthreads/lib -Xlinker -R/u/pabuhr/software/qthreads/lib $(srcdir)/ctxswitch/qthreads.c -lqthread 214 229 215 230 ## ========================================================================================================= … … 305 320 creation-upp_thread.run \ 306 321 creation-goroutine.run \ 307 creation-java_thread.run 322 creation-java_thread.run \ 323 creation-qthreads.run 308 324 309 325 creation-cfa_coroutine$(EXEEXT): … … 333 349 @echo "java JavaThread" >> a.out 334 350 @chmod a+x a.out 351 352 creation-qthreads$(EXEEXT): 353 $(BENCH_V_QTHREADS)$(COMPILE) -DBENCH_N=50000000 -I/u/pabuhr/software/qthreads/include -L/u/pabuhr/software/qthreads/lib -Xlinker -R/u/pabuhr/software/qthreads/lib $(srcdir)/ctxswitch/qthreads.c -lqthread 335 354 336 355 ## ========================================================================================================= … … 375 394 compile-typeof$(EXEEXT): 376 395 @$(CFACOMPILE) -fsyntax-only -w $(testdir)/typeof.cfa 377 -
benchmark/Makefile.in
r18e683b rc1ea11b 371 371 372 372 # applies to both programs 373 AM_CFLAGS = -O2 -Wall -Wextra - Werror -I$(srcdir) -lrt -pthread373 AM_CFLAGS = -O2 -Wall -Wextra -I$(srcdir) -lrt -pthread # -Werror 374 374 AM_CFAFLAGS = -quiet -nodebug -in-tree 375 375 AM_UPPFLAGS = -quiet -nodebug -multi -std=c++14 … … 380 380 BENCH_V_JAVAC = $(__bench_v_JAVAC_$(__quiet)) 381 381 BENCH_V_UPP = $(__bench_v_UPP_$(__quiet)) 382 BENCH_V_QTHREAD = $(__bench_v_QTHREAD_$(__quiet)) 382 383 __quiet = verbose 383 384 __bench_v_CC_quiet = @ … … 393 394 __bench_v_JAVAC_verbose = $(AM_V_JAVAC) 394 395 __bench_v_UPP_verbose = $(AM_V_UPP) 396 __bench_v_QTHREAD_verbose = $(AM_V_CC) 395 397 TOOLSDIR = ${abs_top_builddir}/tools/ 396 398 REPEAT = ${abs_top_builddir}/tools/repeat 397 399 STATS = ${abs_top_srcdir}/tools/stat.py 398 repeats = 3 0400 repeats = 3 # 30 399 401 skipcompile = no 400 402 TIME_FORMAT = "%E" … … 402 404 dummy_SOURCES = dummyC.c dummyCXX.cpp 403 405 FIX_NEW_LINES = cat $@ | tr "\n" "\t" | sed -r 's/\t,/,/' | tr "\t" "\n" > $@ 404 CTXSWITCH_DEPEND = loop.run function.run fetch_add.run \406 CTXSWITCH_DEPEND = loop.run function.run fetch_add.run ttst_lock.run \ 405 407 tls-fetch_add.run ctxswitch-pthread.run \ 406 ctxswitch-cfa_coroutine.run ctxswitch-cfa_thread.run \ 407 ctxswitch-cfa_thread2.run ctxswitch-upp_coroutine.run \ 408 ctxswitch-upp_thread.run ctxswitch-goroutine.run \ 409 ctxswitch-java_thread.run $(am__append_1) 408 ctxswitch-cfa_generator.run ctxswitch-cfa_coroutine.run \ 409 ctxswitch-cfa_thread.run ctxswitch-cfa_thread2.run \ 410 ctxswitch-upp_coroutine.run ctxswitch-upp_thread.run \ 411 ctxswitch-goroutine.run ctxswitch-java_thread.run \ 412 ctxswitch-qthreads.run $(am__append_1) 410 413 testdir = $(top_srcdir)/tests 411 414 all: all-am … … 784 787 785 788 ctxswitch.csv: 786 @echo "coroutine,thread" > $@ 789 @echo "generator,coroutine,thread" > $@ 790 @+make ctxswitch-cfa_generator.runquiet >> $@ && echo -n ',' >> $@ 787 791 @+make ctxswitch-cfa_coroutine.runquiet >> $@ && echo -n ',' >> $@ 788 792 @+make ctxswitch-cfa_thread.runquiet >> $@ … … 812 816 $(BENCH_V_CC)$(COMPILE) -DBENCH_N=500000000 $(srcdir)/fetch_add.c 813 817 818 ttst_lock$(EXEEXT): 819 $(BENCH_V_CC)$(COMPILE) -DBENCH_N=500000000 $(srcdir)/ttst_lock.c 820 814 821 tls-fetch_add$(EXEEXT): 815 822 $(BENCH_V_CC)$(COMPILE) -DBENCH_N=500000000 $(srcdir)/tls-fetch_add.c … … 825 832 ctxswitch-pthread$(EXEEXT): 826 833 $(BENCH_V_CC)$(COMPILE) -DBENCH_N=50000000 $(srcdir)/ctxswitch/pthreads.c 834 835 ctxswitch-cfa_generator$(EXEEXT): 836 $(BENCH_V_CFA)$(CFACOMPILE) -DBENCH_N=50000000 $(srcdir)/ctxswitch/cfa_gen.cfa 827 837 828 838 ctxswitch-cfa_coroutine$(EXEEXT): … … 849 859 @echo "java JavaThread" >> a.out 850 860 @chmod a+x a.out 861 862 ctxswitch-qthreads$(EXEEXT): 863 $(BENCH_V_QTHREADS)$(COMPILE) -DBENCH_N=50000000 -I/u/pabuhr/software/qthreads/include -L/u/pabuhr/software/qthreads/lib -Xlinker -R/u/pabuhr/software/qthreads/lib $(srcdir)/ctxswitch/qthreads.c -lqthread 851 864 852 865 mutex$(EXEEXT) :\ … … 937 950 creation-upp_thread.run \ 938 951 creation-goroutine.run \ 939 creation-java_thread.run 952 creation-java_thread.run \ 953 creation-qthreads.run 940 954 941 955 creation-cfa_coroutine$(EXEEXT): … … 965 979 @echo "java JavaThread" >> a.out 966 980 @chmod a+x a.out 981 982 creation-qthreads$(EXEEXT): 983 $(BENCH_V_QTHREADS)$(COMPILE) -DBENCH_N=50000000 -I/u/pabuhr/software/qthreads/include -L/u/pabuhr/software/qthreads/lib -Xlinker -R/u/pabuhr/software/qthreads/lib $(srcdir)/ctxswitch/qthreads.c -lqthread 967 984 968 985 compile$(EXEEXT) :\ -
benchmark/bench.h
r18e683b rc1ea11b 45 45 statement; \ 46 46 EndTime = bench_time(); \ 47 unsigned long long intoutput = \48 ( EndTime - StartTime ) / n;47 double output = \ 48 (double)( EndTime - StartTime ) / n; 49 49 50 50 #if defined(__cforall) -
benchmark/creation/cfa_cor.cfa
r18e683b rc1ea11b 10 10 #endif 11 11 } 12 void main(MyCoroutine & this) {}12 void main(MyCoroutine &) {} 13 13 14 14 int main(int argc, char* argv[]) { 15 15 BENCH( 16 for ( size_t i = 0; i < n; i++) {16 for ( i; n ) { 17 17 MyCoroutine m; 18 18 }, … … 20 20 ) 21 21 22 printf("% llu\n", result);22 printf("%g\n", result); 23 23 } -
benchmark/creation/cfa_thrd.cfa
r18e683b rc1ea11b 5 5 6 6 thread MyThread {}; 7 void main(MyThread & this) {}7 void main(MyThread &) {} 8 8 9 9 int main(int argc, char* argv[]) { 10 10 BENCH( 11 for ( size_t i = 0; i < n; i++) {11 for ( i; n ) { 12 12 MyThread m; 13 13 }, … … 15 15 ) 16 16 17 printf("% llu\n", result);17 printf("%g\n", result); 18 18 } -
benchmark/creation/pthreads.c
r18e683b rc1ea11b 25 25 ) 26 26 27 printf("% llu\n", result);27 printf("%g\n", result); 28 28 } -
benchmark/creation/upp_cor.cc
r18e683b rc1ea11b 15 15 ) 16 16 17 printf("% llu\n", result);17 printf("%g\n", result); 18 18 } -
benchmark/creation/upp_thrd.cc
r18e683b rc1ea11b 15 15 ) 16 16 17 printf("% llu\n", result);17 printf("%g\n", result); 18 18 } -
benchmark/ctxswitch/cfa_cor.cfa
r18e683b rc1ea11b 1 #include <stdio.h>2 1 #include <kernel.hfa> 3 2 #include <thread.hfa> … … 21 20 22 21 BENCH( 23 for ( size_t i = 0; i < n; i++) {22 for ( i; n ) { 24 23 resume( s ); 25 24 }, … … 27 26 ) 28 27 29 printf("% llu\n", result);28 printf("%g\n", result); 30 29 } -
benchmark/ctxswitch/cfa_cor_then.cfa
r18e683b rc1ea11b 1 #include <stdio.h>2 1 #include <kernel.hfa> 3 2 #include <thread.hfa> … … 23 22 24 23 BENCH( 25 for ( size_t i = 0; i < n; i++) {24 for ( i; n ) { 26 25 resume( s ); 27 26 }, … … 29 28 ) 30 29 31 printf("% llu\n", result);30 printf("%g\n", result); 32 31 } -
benchmark/ctxswitch/cfa_thrd.cfa
r18e683b rc1ea11b 1 #include <stdio.h>2 1 #include <thread.hfa> 3 2 … … 6 5 int main(int argc, char* argv[]) { 7 6 BENCH( 8 for ( size_t i = 0; i < n; i++) {7 for ( i; n ) { 9 8 yield(); 10 9 }, … … 12 11 ) 13 12 14 printf("% llu\n", result);13 printf("%g\n", result); 15 14 } -
benchmark/ctxswitch/cfa_thrd2.cfa
r18e683b rc1ea11b 1 #include <stdio.h>2 1 #include <thread.hfa> 3 2 … … 17 16 Fibre f1; 18 17 BENCH( 19 for ( size_t i = 0; i < n; i++) {18 for ( i; n ) { 20 19 yield(); 21 20 }, … … 23 22 ) 24 23 25 printf("% llu\n", result);24 printf("%g\n", result); 26 25 done = true; 27 26 return 0; -
benchmark/ctxswitch/kos_fibre.cpp
r18e683b rc1ea11b 10 10 result 11 11 ) 12 printf("% llu\n", result);12 printf("%g\n", result); 13 13 return 0; 14 14 } -
benchmark/ctxswitch/kos_fibre2.cpp
r18e683b rc1ea11b 19 19 result 20 20 ) 21 printf("% llu\n", result);21 printf("%g\n", result); 22 22 done = true; 23 23 Fibre::yield(); -
benchmark/ctxswitch/pthreads.c
r18e683b rc1ea11b 14 14 ) 15 15 16 printf("% llu\n", result);16 printf("%g\n", result); 17 17 } -
benchmark/ctxswitch/upp_cor.cc
r18e683b rc1ea11b 30 30 ) 31 31 32 printf("% llu\n", result);32 printf("%g\n", result); 33 33 } -
benchmark/ctxswitch/upp_thrd.cc
r18e683b rc1ea11b 11 11 ) 12 12 13 printf("% llu\n", result);13 printf("%g\n", result); 14 14 } -
benchmark/fetch_add.c
r18e683b rc1ea11b 19 19 ) 20 20 21 printf("% llu\n", result);21 printf("%g\n", result); 22 22 } -
benchmark/function.c
r18e683b rc1ea11b 15 15 ) 16 16 17 printf("% llu\n", result);17 printf("%g\n", result); 18 18 } -
benchmark/loop.c
r18e683b rc1ea11b 11 11 ) 12 12 13 printf("% llu\n", result);13 printf("%g\n", result); 14 14 } -
benchmark/mutex/cfa1.cfa
r18e683b rc1ea11b 10 10 M m; 11 11 BENCH( 12 for ( size_t i = 0; i < n; i++) {12 for ( i; n ) { 13 13 call(m); 14 14 }, … … 16 16 ) 17 17 18 printf("% llu\n", result);18 printf("%g\n", result); 19 19 } -
benchmark/mutex/cfa2.cfa
r18e683b rc1ea11b 10 10 M m1, m2; 11 11 BENCH( 12 for ( size_t i = 0; i < n; i++) {12 for ( i; n ) { 13 13 call(m1, m2); 14 14 }, … … 16 16 ) 17 17 18 printf("% llu\n", result);18 printf("%g\n", result); 19 19 } -
benchmark/mutex/cfa4.cfa
r18e683b rc1ea11b 11 11 M m1, m2, m3, m4; 12 12 BENCH( 13 for ( size_t i = 0; i < n; i++) {13 for ( i; n ) { 14 14 call(m1, m2, m3, m4); 15 15 }, … … 17 17 ) 18 18 19 printf("% llu\n", result);19 printf("%g\n", result); 20 20 } -
benchmark/mutex/pthreads.c
r18e683b rc1ea11b 19 19 ) 20 20 21 printf("% llu\n", result);21 printf("%g\n", result); 22 22 } -
benchmark/mutex/upp.cc
r18e683b rc1ea11b 17 17 ) 18 18 19 printf("% llu\n", result);19 printf("%g\n", result); 20 20 } -
benchmark/schedext/cfa1.cfa
r18e683b rc1ea11b 18 18 go = 1; 19 19 BENCH( 20 for ( size_t i = 0; i < n; i++) {20 for ( i; n ) { 21 21 waitfor(call, a1); 22 22 }, … … 24 24 ) 25 25 26 printf("% llu\n", result);26 printf("%g\n", result); 27 27 go = 0; 28 28 return 0; … … 31 31 thread T {}; 32 32 void ^?{}( T & mutex this ) {} 33 void main( T & this) {33 void main( T & ) { 34 34 while(go == 0) { yield(); } 35 35 while(go == 1) { call(m1); } … … 37 37 } 38 38 39 int main(int margc, char* margv[]) { 40 argc = margc; 41 argv = margv; 39 int main(__attribute__((unused)) int argc, __attribute__((unused)) char* argv[]) { 42 40 T t; 43 41 return wait(m1); -
benchmark/schedext/cfa2.cfa
r18e683b rc1ea11b 18 18 go = 1; 19 19 BENCH( 20 for ( size_t i = 0; i < n; i++) {20 for ( i; n ) { 21 21 waitfor(call, a1, a2); 22 22 }, … … 24 24 ) 25 25 26 printf("% llu\n", result);26 printf("%g\n", result); 27 27 go = 0; 28 28 return 0; … … 31 31 thread T {}; 32 32 void ^?{}( T & mutex this ) {} 33 void main( T & this) {33 void main( T & ) { 34 34 while(go == 0) { yield(); } 35 35 while(go == 1) { call(m1, m2); } … … 37 37 } 38 38 39 int main(int margc, char* margv[]) { 40 argc = margc; 41 argv = margv; 39 int main(__attribute__((unused)) int argc, __attribute__((unused)) char* argv[]) { 42 40 T t; 43 41 return wait(m1, m2); -
benchmark/schedext/cfa4.cfa
r18e683b rc1ea11b 18 18 go = 1; 19 19 BENCH( 20 for ( size_t i = 0; i < n; i++) {20 for ( i; n ) { 21 21 waitfor(call, a1, a2, a3, a4); 22 22 }, … … 24 24 ) 25 25 26 printf("% llu\n", result);26 printf("%g\n", result); 27 27 go = 0; 28 28 return 0; … … 31 31 thread T {}; 32 32 void ^?{}( T & mutex this ) {} 33 void main( T & this) {33 void main( T & ) { 34 34 while(go == 0) { yield(); } 35 35 while(go == 1) { call(m1, m2, m3, m4); } … … 37 37 } 38 38 39 int main(int margc, char* margv[]) { 40 argc = margc; 41 argv = margv; 39 int main(__attribute__((unused)) int argc, __attribute__((unused)) char* argv[]) { 42 40 T t; 43 41 return wait(m1, m2, m3, m4); -
benchmark/schedext/upp.cc
r18e683b rc1ea11b 20 20 ) 21 21 22 printf("% llu\n", result);22 printf("%g\n", result); 23 23 go = 0; 24 24 return 0; -
benchmark/schedint/cfa1.cfa
r18e683b rc1ea11b 21 21 go = 1; 22 22 BENCH( 23 for ( size_t i = 0; i < n; i++) {23 for ( i; n ) { 24 24 wait(c); 25 25 }, … … 27 27 ) 28 28 29 printf("% llu\n", result);29 printf("%g\n", result); 30 30 go = 0; 31 31 return 0; … … 33 33 34 34 thread T {}; 35 void ^?{}( T & mutex this) {}36 void main( T & this) {35 void ^?{}( T & mutex ) {} 36 void main( T & ) { 37 37 while(go == 0) { yield(); } 38 38 while(go == 1) { call(m1); } … … 40 40 } 41 41 42 int main(int margc, char* margv[]) { 43 argc = margc; 44 argv = margv; 42 int main(__attribute__((unused)) int argc, __attribute__((unused)) char* argv[]) { 45 43 T t; 46 44 return wait(m1); -
benchmark/schedint/cfa2.cfa
r18e683b rc1ea11b 21 21 go = 1; 22 22 BENCH( 23 for ( size_t i = 0; i < n; i++) {23 for ( i; n ) { 24 24 wait(c); 25 25 }, … … 27 27 ) 28 28 29 printf("% llu\n", result);29 printf("%g\n", result); 30 30 go = 0; 31 31 return 0; … … 34 34 thread T {}; 35 35 void ^?{}( T & mutex this ) {} 36 void main( T & this) {36 void main( T & ) { 37 37 while(go == 0) { yield(); } 38 38 while(go == 1) { call(m1, m2); } … … 40 40 } 41 41 42 int main(int margc, char* margv[]) { 43 argc = margc; 44 argv = margv; 42 int main(__attribute__((unused)) int argc, __attribute__((unused)) char* argv[]) { 45 43 T t; 46 44 return wait(m1, m2); -
benchmark/schedint/cfa4.cfa
r18e683b rc1ea11b 21 21 go = 1; 22 22 BENCH( 23 for ( size_t i = 0; i < n; i++) {23 for ( i; n ) { 24 24 wait(c); 25 25 }, … … 27 27 ) 28 28 29 printf("% llu\n", result);29 printf("%g\n", result); 30 30 go = 0; 31 31 return 0; … … 34 34 thread T {}; 35 35 void ^?{}( T & mutex this ) {} 36 void main( T & this) {36 void main( T & ) { 37 37 while(go == 0) { yield(); } 38 38 while(go == 1) { call(m1, m2, m3, m4); } … … 40 40 } 41 41 42 int main(int margc, char* margv[]) { 43 argc = margc; 44 argv = margv; 42 int main(__attribute__((unused)) int argc, __attribute__((unused)) char* argv[]) { 45 43 T t; 46 44 return wait(m1, m2, m3, m4); -
benchmark/schedint/pthreads.c
r18e683b rc1ea11b 27 27 ) 28 28 29 printf("% llu\n", result);29 printf("%g\n", result); 30 30 go = 0; 31 31 pthread_mutex_unlock(&m); … … 33 33 } 34 34 35 void* thread_main( void * a) {35 void* thread_main(__attribute__((unused)) void * arg ) { 36 36 while(go == 0) { sched_yield(); } 37 37 while(go == 1) { call(); } … … 39 39 } 40 40 41 int main(int margc, char* margv[]) { 42 argc = margc; 43 argv = margv; 41 int main(__attribute__((unused)) int argc, __attribute__((unused)) char* argv[]) { 44 42 pthread_t thread; 45 43 if (pthread_create(&thread, NULL, thread_main, NULL) < 0) { -
benchmark/schedint/upp.cc
r18e683b rc1ea11b 23 23 ) 24 24 25 printf("% llu\n", result);25 printf("%g\n", result); 26 26 go = 0; 27 27 return 0; … … 39 39 }; 40 40 41 int main(int margc, char* margv[]) { 42 argc = margc; 43 argv = margv; 41 int main(__attribute__((unused)) int argc, __attribute__((unused)) char* argv[]) { 44 42 T t; 45 43 return m.wait(); -
benchmark/tls-fetch_add.c
r18e683b rc1ea11b 24 24 ) 25 25 26 printf("% llu\n", result);26 printf("%g\n", result); 27 27 } -
doc/bibliography/pl.bib
r18e683b rc1ea11b 948 948 author = {{\textsf{C}{$\mathbf{\forall}$} Features}}, 949 949 howpublished= {\href{https://plg.uwaterloo.ca/~cforall/features}{https://\-plg.uwaterloo.ca/\-$\sim$cforall/\-features}}, 950 } 951 952 @misc{CforallBenchMarks, 953 contributer = {pabuhr@plg}, 954 key = {Cforall Benchmarks}, 955 author = {{\textsf{C}{$\mathbf{\forall}$} Benchmarks}}, 956 howpublished= {\href{https://plg.uwaterloo.ca/~cforall/benchmarks}{https://\-plg.uwaterloo.ca/\-$\sim$cforall/\-benchmarks}}, 950 957 } 951 958 … … 1919 1926 year = 1965, 1920 1927 note = {Reprinted in \cite{Genuys68} pp. 43--112.} 1928 } 1929 1930 @inproceedings{Adya02, 1931 contributer = {pabuhr@plg}, 1932 author = {Adya, Atul and Howell, Jon and Theimer, Marvin and Bolosky, William J. and Douceur, John R.}, 1933 title = {Cooperative Task Management Without Manual Stack Management}, 1934 booktitle = {Proceedings of the General Track of the Annual Conference on USENIX Annual Technical Conference}, 1935 series = {ATEC '02}, 1936 year = {2002}, 1937 pages = {289-302}, 1938 publisher = {USENIX Association}, 1939 address = {Berkeley, CA, USA}, 1940 } 1941 1942 @misc{CoroutineTS, 1943 keywords = {Coroutines TS, C++20, working draft}, 1944 contributer = {pabuhr@plg}, 1945 author = {Gor Nishanov}, 1946 title = {Merge Coroutines TS into C++20 Working Draft}, 1947 year = 2019, 1948 month = feb, 1949 howpublished= {\href{http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2019/p0912r5.html} 1950 {http://\-www.open-std.org/\-jtc1/\-sc22/\-wg21/\-docs/\-papers/\-2019/p0912r5.html}}, 1921 1951 } 1922 1952 … … 4359 4389 } 4360 4390 4391 4361 4392 @article{Liskov86, 4362 4393 keywords = {synchronous communication, concurrency}, … … 4371 4402 year = {}, 4372 4403 pages = {}, 4404 } 4405 4406 @misc{libdill, 4407 keywords = {libdill/libmill Thread Library}, 4408 contributer = {pabuhr@plg}, 4409 author = {Alex Cornejo, et al}, 4410 title = {libdill Thread Library}, 4411 year = 2019, 4412 howpublished= {\href{http://libdill.org/libdill-2.14.tar.gz} 4413 {http://\-libdill.org/\-libdill-2.14.tar.gz}}, 4373 4414 } 4374 4415 … … 4493 4534 year = 2016, 4494 4535 howpublished= {\href{http://blog.reverberate.org/2016/01/making-arbitrarily-large-binaries-from.html} 4495 { 4496 {http://blog.reverberate.org/\-2016/\-01/\-making-arbitrarily-large-binaries-from.html} 4497 }}, 4536 {http://blog.reverberate.org/\-2016/\-01/\-making-arbitrarily-large-binaries-from.html}}, 4498 4537 optnote = {Accessed: 2016-09}, 4499 4538 } … … 4517 4556 trivial changes to the source code of the library. 4518 4557 } 4558 } 4559 4560 @misc{Marcel, 4561 keywords = {Marcel Thread Library}, 4562 contributer = {pabuhr@plg}, 4563 author = {Gabriel Antoniu, et al}, 4564 title = {Marcel Thread Library}, 4565 year = 2011, 4566 howpublished= {\href{https://gforge.inria.fr/frs/download.php/file/28643/marcel-2.99.3.tar.gz} 4567 {https://\-gforge.inria.fr/\-frs/\-download.php/\-file/\-28643/\-marcel-2.99.3.tar.gz}}, 4519 4568 } 4520 4569 -
doc/papers/AMA/AMA-stix/ama/WileyNJD-v2.cls
r18e683b rc1ea11b 2444 2444 \@afterheading} 2445 2445 2446 \renewcommand\section{\@startsection{section}{1}{\z@}{-2 7pt \@plus -2pt \@minus -2pt}{12\p@}{\sectionfont}}%2447 \renewcommand\subsection{\@startsection{subsection}{2}{\z@}{-2 3pt \@plus -2pt \@minus -2pt}{5\p@}{\subsectionfont}}%2446 \renewcommand\section{\@startsection{section}{1}{\z@}{-25pt \@plus -2pt \@minus -2pt}{12\p@}{\sectionfont}}% 2447 \renewcommand\subsection{\@startsection{subsection}{2}{\z@}{-22pt \@plus -2pt \@minus -2pt}{5\p@}{\subsectionfont}}% 2448 2448 \renewcommand\subsubsection{\@startsection{subsubsection}{3}{\z@}{-20pt \@plus -2pt \@minus -2pt}{2\p@}{\subsubsectionfont}}% 2449 2449 % -
doc/papers/concurrency/Paper.tex
r18e683b rc1ea11b 157 157 __float80, float80, __float128, float128, forall, ftype, generator, _Generic, _Imaginary, __imag, __imag__, 158 158 inline, __inline, __inline__, __int128, int128, __label__, monitor, mutex, _Noreturn, one_t, or, 159 otype, restrict, __restrict, __restrict__, __signed, __signed__, _Static_assert, suspend,thread,159 otype, restrict, __restrict, __restrict__, __signed, __signed__, _Static_assert, thread, 160 160 _Thread_local, throw, throwResume, timeout, trait, try, ttype, typeof, __typeof, __typeof__, 161 161 virtual, __volatile, __volatile__, waitfor, when, with, zero_t}, … … 303 303 However, \Celeven concurrency is largely wrappers for a subset of the pthreads library~\cite{Butenhof97,Pthreads}, and \Celeven and pthreads concurrency is simple, based on thread fork/join in a function and a few locks, which is low-level and error prone; 304 304 no high-level language concurrency features are defined. 305 Interestingly, almost a decade after publication of the \Celeven standard, neither gcc-8, clang- 8nor msvc-19 (most recent versions) support the \Celeven include @threads.h@, indicating little interest in the C11 concurrency approach.305 Interestingly, almost a decade after publication of the \Celeven standard, neither gcc-8, clang-9 nor msvc-19 (most recent versions) support the \Celeven include @threads.h@, indicating little interest in the C11 concurrency approach. 306 306 Finally, while the \Celeven standard does not state a threading model, the historical association with pthreads suggests implementations would adopt kernel-level threading (1:1)~\cite{ThreadModel}. 307 307 … … 313 313 From 2000 onwards, languages like Go~\cite{Go}, Erlang~\cite{Erlang}, Haskell~\cite{Haskell}, D~\cite{D}, and \uC~\cite{uC++,uC++book} have championed the M:N user-threading model, and many user-threading libraries have appeared~\cite{Qthreads,MPC,Marcel}, including putting green threads back into Java~\cite{Quasar}. 314 314 The main argument for user-level threading is that they are lighter weight than kernel threads (locking and context switching do not cross the kernel boundary), so there is less restriction on programming styles that encourage large numbers of threads performing medium work-units to facilitate load balancing by the runtime~\cite{Verch12}. 315 As well, user-threading facilitates a simpler concurrency approach using thread objects that leverage sequential patterns versus events with call-backs~\cite{ vonBehren03}.315 As well, user-threading facilitates a simpler concurrency approach using thread objects that leverage sequential patterns versus events with call-backs~\cite{Adya02,vonBehren03}. 316 316 Finally, performant user-threading implementations (both time and space) meet or exceed direct kernel-threading implementations, while achieving the programming advantages of high concurrency levels and safety. 317 317 … … 613 613 Finally, an explicit generator type provides both design and performance benefits, such as multiple type-safe interface functions taking and returning arbitrary types. 614 614 \begin{cfa} 615 int ?()( Fib & fib ) with( fib ) { return `resume( fib )`.fn; } // function-call interface616 int ?()( Fib & fib, int N ) with( fib ) { for ( N - 1 ) `fib()`; return `fib()`; } // use simple interface617 double ?()( Fib & fib ) with( fib ) { return (int)`fib()` / 3.14159; } // cast prevents recursive call618 sout | (int)f1() | (double)f1() | f2( 2 ); // simple interface, cast selects call based on return type, step 2 values615 int ?()( Fib & fib ) { return `resume( fib )`.fn; } $\C[3.9in]{// function-call interface}$ 616 int ?()( Fib & fib, int N ) { for ( N - 1 ) `fib()`; return `fib()`; } $\C{// use function-call interface to skip N values}$ 617 double ?()( Fib & fib ) { return (int)`fib()` / 3.14159; } $\C{// different return type, cast prevents recursive call}\CRT$ 618 sout | (int)f1() | (double)f1() | f2( 2 ); // alternative interface, cast selects call based on return type, step 2 values 619 619 \end{cfa} 620 620 Now, the generator can be a separately-compiled opaque-type only accessed through its interface functions. … … 628 628 With respect to safety, we believe static analysis can discriminate local state from temporary variables in a generator, \ie variable usage spanning @suspend@, and generate a compile-time error. 629 629 Finally, our current experience is that most generator problems have simple data state, including local state, but complex execution state, so the burden of creating the generator type is small. 630 As well, C programmers are not afraid withthis kind of semantic programming requirement, if it results in very small, fast generators.630 As well, C programmers are not afraid of this kind of semantic programming requirement, if it results in very small, fast generators. 631 631 632 632 Figure~\ref{f:CFAFormatGen} shows an asymmetric \newterm{input generator}, @Fmt@, for restructuring text into groups of characters of fixed-size blocks, \ie the input on the left is reformatted into the output on the right, where newlines are ignored. … … 796 796 This semantics is basically a tail-call optimization, which compilers already perform. 797 797 The example shows the assembly code to undo the generator's entry code before the direct jump. 798 This assembly code depends on what entry code is generated, specifically if there are local variables and the level of optimization.798 This assembly code depends on what entry code is generated, specifically if there are local variables, and the level of optimization. 799 799 To provide this new calling convention requires a mechanism built into the compiler, which is beyond the scope of \CFA at this time. 800 800 Nevertheless, it is possible to hand generate any symmetric generators for proof of concept and performance testing. 801 A compiler could also eliminate other artifacts in the generator simulation to further increase performance .801 A compiler could also eliminate other artifacts in the generator simulation to further increase performance, \eg LLVM has various coroutine support~\cite{CoroutineTS}, and \CFA can leverage this support should it fork @clang@. 802 802 803 803 \begin{figure} … … 1213 1213 Hence, a compromise solution is necessary that works for asymmetric (acyclic) and symmetric (cyclic) coroutines. 1214 1214 1215 Our solution for coroutine termination works well for the most common asymmetric and symmetric coroutine usage-patterns. 1215 Our solution is to context switch back to the first resumer (starter) once the coroutine ends. 1216 This semantics works well for the most common asymmetric and symmetric coroutine usage-patterns. 1216 1217 For asymmetric coroutines, it is common for the first resumer (starter) coroutine to be the only resumer. 1217 1218 All previous generators converted to coroutines have this property. … … 1245 1246 1246 1247 1247 \subsection{ (Generator)Coroutine Implementation}1248 \subsection{Generator / Coroutine Implementation} 1248 1249 1249 1250 A significant implementation challenge for generators/coroutines (and threads in Section~\ref{s:threads}) is adding extra fields to the custom types and related functions, \eg inserting code after/before the coroutine constructor/destructor and @main@ to create/initialize/de-initialize/destroy any extra fields, \eg stack. … … 1254 1255 class myCoroutine inherits baseCoroutine { ... } 1255 1256 \end{cfa} 1256 The problem is that the programming language and its tool chain, \eg debugger, @valgrind@, need to understand @baseCoroutine@ because it infers special property, so type @baseCoroutine@ becomes a de facto keyword and all types inheriting from it are implicitly custom types.1257 As well,some special properties are not handled by existing language semantics, \eg the execution of constructors/destructors is in the wrong order to implicitly start threads because the thread must start \emph{after} all constructors as it relies on a completely initialized object, but the inherited constructor runs \emph{before} the derived.1257 % The problem is that the programming language and its tool chain, \eg debugger, @valgrind@, need to understand @baseCoroutine@ because it infers special property, so type @baseCoroutine@ becomes a de facto keyword and all types inheriting from it are implicitly custom types. 1258 The problem is that some special properties are not handled by existing language semantics, \eg the execution of constructors/destructors is in the wrong order to implicitly start threads because the thread must start \emph{after} all constructors as it relies on a completely initialized object, but the inherited constructor runs \emph{before} the derived. 1258 1259 Alternatives, such as explicitly starting threads as in Java, are repetitive and forgetting to call start is a common source of errors. 1259 1260 An alternative is composition: … … 1267 1268 However, there is nothing preventing wrong placement or multiple declarations. 1268 1269 1269 \CFA custom types make any special properties explicit to the language and its tool chain, \eg the language code-generator knows where to inject code and when it is unsafe to perform certain optimizations, and IDEs using simple parsing can find and manipulate types with special properties. 1270 \CFA custom types make any special properties explicit to the language and its tool chain, \eg the language code-generator knows where to inject code 1271 % and when it is unsafe to perform certain optimizations, 1272 and IDEs using simple parsing can find and manipulate types with special properties. 1270 1273 The downside of this approach is that it makes custom types a special case in the language. 1271 1274 Users wanting to extend custom types or build their own can only do so in ways offered by the language. … … 1282 1285 \end{cfa} 1283 1286 Note, copying generators/coroutines/threads is not meaningful. 1284 For example, a coroutine retains its last resumer and suspends back to it;1285 having a copy also suspend back to the same resumer is undefined semantics.1287 For example, both the resumer and suspender descriptors can have bi-directional pointers; 1288 copying these coroutines does not update the internal pointers so behaviour of both copies would be difficult to understand. 1286 1289 Furthermore, two coroutines cannot logically execute on the same stack. 1287 1290 A deep coroutine copy, which copies the stack, is also meaningless in an unmanaged language (no garbage collection), like C, because the stack may contain pointers to object within it that require updating for the copy. 1288 1291 The \CFA @dtype@ property provides no \emph{implicit} copying operations and the @is_coroutine@ trait provides no \emph{explicit} copying operations, so all coroutines must be passed by reference (pointer). 1289 The function definitions ensures there is a statically-typed @main@ function that is the starting point (first stack frame) of a coroutine, and a mechanism to get (read) the c urrently executing coroutinehandle.1292 The function definitions ensures there is a statically-typed @main@ function that is the starting point (first stack frame) of a coroutine, and a mechanism to get (read) the coroutine descriptor from its handle. 1290 1293 The @main@ function has no return value or additional parameters because the coroutine type allows an arbitrary number of interface functions with corresponding arbitrary typed input/output values versus fixed ones. 1291 1294 The advantage of this approach is that users can easily create different types of coroutines, \eg changing the memory layout of a coroutine is trivial when implementing the @get_coroutine@ function, and possibly redefining \textsf{suspend} and @resume@. … … 1493 1496 \end{tabular} 1494 1497 \end{cquote} 1495 Like coroutines, the @dtype@ property prevents \emph{implicit} copy operations and the @is_ coroutine@ trait provides no \emph{explicit} copy operations, so threads must be passed by reference (pointer).1496 Similarly, the function definitions ensures there is a statically-typed @main@ function that is the thread starting point (first stack frame), a mechanism to get (read) the currently executing threadhandle, and a special destructor to prevent deallocation while the thread is executing.1498 Like coroutines, the @dtype@ property prevents \emph{implicit} copy operations and the @is_thread@ trait provides no \emph{explicit} copy operations, so threads must be passed by reference (pointer). 1499 Similarly, the function definitions ensures there is a statically-typed @main@ function that is the thread starting point (first stack frame), a mechanism to get (read) the thread descriptor from its handle, and a special destructor to prevent deallocation while the thread is executing. 1497 1500 (The qualifier @mutex@ for the destructor parameter is discussed in Section~\ref{s:Monitor}.) 1498 1501 The difference between the coroutine and thread is that a coroutine borrows a thread from its caller, so the first thread resuming a coroutine creates the coroutine's stack and starts running the coroutine main on the stack; … … 1617 1620 % Copying a lock is insecure because it is possible to copy an open lock and then use the open copy when the original lock is closed to simultaneously access the shared data. 1618 1621 % Copying a monitor is secure because both the lock and shared data are copies, but copying the shared data is meaningless because it no longer represents a unique entity. 1619 Similarly, the function definitions ensures there is a mechanism to get (read) the currently executing monitorhandle, and a special destructor to prevent deallocation if a thread using the shared data.1622 Similarly, the function definitions ensures there is a mechanism to get (read) the monitor descriptor from its handle, and a special destructor to prevent deallocation if a thread using the shared data. 1620 1623 The custom monitor type also inserts any locks needed to implement the mutual exclusion semantics. 1621 1624 … … 1656 1659 called \newterm{bulk acquire}. 1657 1660 \CFA guarantees acquisition order is consistent across calls to @mutex@ functions using the same monitors as arguments, so acquiring multiple monitors is safe from deadlock. 1658 Figure~\ref{f:BankTransfer} shows a trivial solution to the bank transfer problem , where two resources must be locked simultaneously, using \CFA monitors with implicit locking and \CC with explicit locking.1661 Figure~\ref{f:BankTransfer} shows a trivial solution to the bank transfer problem~\cite{BankTransfer}, where two resources must be locked simultaneously, using \CFA monitors with implicit locking and \CC with explicit locking. 1659 1662 A \CFA programmer only has to manage when to acquire mutual exclusion; 1660 1663 a \CC programmer must select the correct lock and acquisition mechanism from a panoply of locking options. … … 1800 1803 Figure~\ref{f:MonitorScheduling} shows general internal/external scheduling (for the bounded-buffer example in Figure~\ref{f:InternalExternalScheduling}). 1801 1804 External calling threads block on the calling queue, if the monitor is occupied, otherwise they enter in FIFO order. 1802 Internal threads block on condition queues via @wait@ and they reenter from the condition in FIFO order, or they block on urgent via @signal_block@ or @waitfor@ and reenter implicit when the monitor becomes empty, \ie, the thread in the monitor exits or waits. 1805 Internal threads block on condition queues via @wait@ and reenter from the condition in FIFO order. 1806 Alternatively, internal threads block on urgent from the @signal_block@ or @waitfor@, and reenter implicitly when the monitor becomes empty, \ie, the thread in the monitor exits or waits. 1803 1807 1804 1808 There are three signalling mechanisms to unblock waiting threads to enter the monitor. 1805 Note, signalling cannot have the signaller and signalled thread in the monitor simultaneously because of the mutual exclusion so only one can proceed.1809 Note, signalling cannot have the signaller and signalled thread in the monitor simultaneously because of the mutual exclusion, so either the signaller or signallee can proceed. 1806 1810 For internal scheduling, threads are unblocked from condition queues using @signal@, where the signallee is moved to urgent and the signaller continues (solid line). 1807 1811 Multiple signals move multiple signallees to urgent, until the condition is empty. … … 1843 1847 It is common to declare condition variables as monitor fields to prevent shared access, hence no locking is required for access as the conditions are protected by the monitor lock. 1844 1848 In \CFA, a condition variable can be created/stored independently. 1845 To still prevent expensive locking on access, a condition variable is tied to a \emph{group} of monitors on first use, called \newterm{branding}, resulting in a low-cost boolen test to detect sharing from other monitors.1849 % To still prevent expensive locking on access, a condition variable is tied to a \emph{group} of monitors on first use, called \newterm{branding}, resulting in a low-cost boolean test to detect sharing from other monitors. 1846 1850 1847 1851 % Signalling semantics cannot have the signaller and signalled thread in the monitor simultaneously, which means: … … 1852 1856 % The signalling thread continues and the signalled thread is marked for urgent unblocking at the next scheduling point (exit/wait). 1853 1857 % \item 1854 % The signalling thread blocks but is marked for urg rent unblocking at the next scheduling point and the signalled thread continues.1858 % The signalling thread blocks but is marked for urgent unblocking at the next scheduling point and the signalled thread continues. 1855 1859 % \end{enumerate} 1856 1860 % The first approach is too restrictive, as it precludes solving a reasonable class of problems, \eg dating service (see Figure~\ref{f:DatingService}). … … 1961 1965 External scheduling is controlled by the @waitfor@ statement, which atomically blocks the calling thread, releases the monitor lock, and restricts the function calls that can next acquire mutual exclusion. 1962 1966 If the buffer is full, only calls to @remove@ can acquire the buffer, and if the buffer is empty, only calls to @insert@ can acquire the buffer. 1963 Calls threads to functions that are currently excludedblock outside of (external to) the monitor on the calling queue, versus blocking on condition queues inside of (internal to) the monitor.1967 Threads calling excluded functions block outside of (external to) the monitor on the calling queue, versus blocking on condition queues inside of (internal to) the monitor. 1964 1968 Figure~\ref{f:RWExt} shows a readers/writer lock written using external scheduling, where a waiting reader detects a writer using the resource and restricts further calls until the writer exits by calling @EndWrite@. 1965 1969 The writer does a similar action for each reader or writer using the resource. … … 2076 2080 For @wait( e )@, the default semantics is to atomically block the signaller and release all acquired mutex parameters, \ie @wait( e, m1, m2 )@. 2077 2081 To override the implicit multi-monitor wait, specific mutex parameter(s) can be specified, \eg @wait( e, m1 )@. 2078 Wait statically verifies the released monitors are the acquired mutex-parameters so unconditional release is safe.2082 Wait cannot statically verifies the released monitors are the acquired mutex-parameters without disallowing separately compiled helper functions calling @wait@. 2079 2083 While \CC supports bulk locking, @wait@ only accepts a single lock for a condition variable, so bulk locking with condition variables is asymmetric. 2080 2084 Finally, a signaller, … … 2088 2092 Similarly, for @waitfor( rtn )@, the default semantics is to atomically block the acceptor and release all acquired mutex parameters, \ie @waitfor( rtn, m1, m2 )@. 2089 2093 To override the implicit multi-monitor wait, specific mutex parameter(s) can be specified, \eg @waitfor( rtn, m1 )@. 2090 @waitfor@ statically verifies the released monitors are the same as the acquired mutex-parameters of the given function or function pointer. 2091 To statically verify the released monitors match with the accepted function's mutex parameters, the function (pointer) prototype must be accessible. 2094 @waitfor@ does statically verify the monitor types passed are the same as the acquired mutex-parameters of the given function or function pointer, hence the function (pointer) prototype must be accessible. 2092 2095 % When an overloaded function appears in an @waitfor@ statement, calls to any function with that name are accepted. 2093 2096 % The rationale is that members with the same name should perform a similar function, and therefore, all should be eligible to accept a call. … … 2148 2151 The right example accepts either @mem1@ or @mem2@ if @C1@ and @C2@ are true. 2149 2152 2150 An interesting use of @waitfor@ is accepting the @mutex@ destructor to know when an object is deallocated. 2151 \begin{cfa} 2152 void insert( Buffer(T) & mutex buffer, T elem ) with( buffer ) { 2153 if ( count == 10 ) 2154 waitfor( remove, buffer ) { 2155 // insert elem into buffer 2156 } or `waitfor( ^?{}, buffer )` throw insertFail; 2157 } 2158 \end{cfa} 2159 When the buffer is deallocated, the current waiter is unblocked and informed, so it can perform an appropriate action. 2160 However, the basic @waitfor@ semantics do not support this functionality, since using an object after its destructor is called is undefined. 2161 Therefore, to make this useful capability work, the semantics for accepting the destructor is the same as @signal@, \ie the call to the destructor is placed on the urgent queue and the acceptor continues execution, which throws an exception to the acceptor and then the caller is unblocked from the urgent queue to deallocate the object. 2162 Accepting the destructor is the idiomatic way to terminate a thread in \CFA. 2153 An interesting use of @waitfor@ is accepting the @mutex@ destructor to know when an object is deallocated, \eg assume the bounded buffer is restructred from a monitor to a thread with the following @main@. 2154 \begin{cfa} 2155 void main( Buffer(T) & buffer ) with(buffer) { 2156 for () { 2157 `waitfor( ^?{}, buffer )` break; 2158 or when ( count != 20 ) waitfor( insert, buffer ) { ... } 2159 or when ( count != 0 ) waitfor( remove, buffer ) { ... } 2160 } 2161 // clean up 2162 } 2163 \end{cfa} 2164 When the program main deallocates the buffer, it first calls the buffer's destructor, which is accepted, the destructor runs, and the buffer is deallocated. 2165 However, the buffer thread cannot continue after the destructor call because the object is gone; 2166 hence, clean up in @main@ cannot occur, which means destructors for local objects are not run. 2167 To make this useful capability work, the semantics for accepting the destructor is the same as @signal@, \ie the destructor call is placed on urgent and the acceptor continues execution, which ends the loop, cleans up, and the thread terminates. 2168 Then, the destructor caller unblocks from urgent to deallocate the object. 2169 Accepting the destructor is the idiomatic way in \CFA to terminate a thread performing direct communication. 2163 2170 2164 2171 … … 2357 2364 2358 2365 struct Msg { int i, j; }; 2359 thread Go rtn { int i; float f; Msg m; };2360 void mem1( Go rtn & mutex gortn, int i ) { gortn.i = i; }2361 void mem2( Go rtn & mutex gortn, float f ) { gortn.f = f; }2362 void mem3( Go rtn & mutex gortn, Msg m ) { gortn.m = m; }2363 void ^?{}( Go rtn & mutex ) {}2364 2365 void main( Go rtn & gortn ) with( gortn ) { // thread starts2366 thread GoRtn { int i; float f; Msg m; }; 2367 void mem1( GoRtn & mutex gortn, int i ) { gortn.i = i; } 2368 void mem2( GoRtn & mutex gortn, float f ) { gortn.f = f; } 2369 void mem3( GoRtn & mutex gortn, Msg m ) { gortn.m = m; } 2370 void ^?{}( GoRtn & mutex ) {} 2371 2372 void main( GoRtn & gortn ) with( gortn ) { // thread starts 2366 2373 2367 2374 for () { … … 2376 2383 } 2377 2384 int main() { 2378 Go rtn gortn; $\C[2.0in]{// start thread}$2385 GoRtn gortn; $\C[2.0in]{// start thread}$ 2379 2386 `mem1( gortn, 0 );` $\C{// different calls}\CRT$ 2380 2387 `mem2( gortn, 2.5 );` … … 2534 2541 % However, preemption is necessary for fairness and to reduce tail-latency. 2535 2542 % For concurrency that relies on spinning, if all cores spin the system is livelocked, whereas preemption breaks the livelock. 2536 % 2537 % 2538 % \subsection{Thread Pools} 2539 % 2540 % In contrast to direct threading is indirect \newterm{thread pools}, \eg Java @executor@, where small jobs (work units) are inserted into a work pool for execution. 2541 % If the jobs are dependent, \ie interact, there is an implicit/explicit dependency graph that ties them together. 2542 % While removing direct concurrency, and hence the amount of context switching, thread pools significantly limit the interaction that can occur among jobs. 2543 % Indeed, jobs should not block because that also blocks the underlying thread, which effectively means the CPU utilization, and therefore throughput, suffers. 2544 % While it is possible to tune the thread pool with sufficient threads, it becomes difficult to obtain high throughput and good core utilization as job interaction increases. 2545 % As well, concurrency errors return, which threads pools are suppose to mitigate. 2543 2544 2545 \begin{comment} 2546 \subsection{Thread Pools} 2547 2548 In contrast to direct threading is indirect \newterm{thread pools}, \eg Java @executor@, where small jobs (work units) are inserted into a work pool for execution. 2549 If the jobs are dependent, \ie interact, there is an implicit/explicit dependency graph that ties them together. 2550 While removing direct concurrency, and hence the amount of context switching, thread pools significantly limit the interaction that can occur among jobs. 2551 Indeed, jobs should not block because that also blocks the underlying thread, which effectively means the CPU utilization, and therefore throughput, suffers. 2552 While it is possible to tune the thread pool with sufficient threads, it becomes difficult to obtain high throughput and good core utilization as job interaction increases. 2553 As well, concurrency errors return, which threads pools are suppose to mitigate. 2554 2555 \begin{figure} 2556 \centering 2557 \begin{tabular}{@{}l|l@{}} 2558 \begin{cfa} 2559 struct Adder { 2560 int * row, cols; 2561 }; 2562 int operator()() { 2563 subtotal = 0; 2564 for ( int c = 0; c < cols; c += 1 ) 2565 subtotal += row[c]; 2566 return subtotal; 2567 } 2568 void ?{}( Adder * adder, int row[$\,$], int cols, int & subtotal ) { 2569 adder.[rows, cols, subtotal] = [rows, cols, subtotal]; 2570 } 2571 2572 2573 2574 2575 \end{cfa} 2576 & 2577 \begin{cfa} 2578 int main() { 2579 const int rows = 10, cols = 10; 2580 int matrix[rows][cols], subtotals[rows], total = 0; 2581 // read matrix 2582 Executor executor( 4 ); // kernel threads 2583 Adder * adders[rows]; 2584 for ( r; rows ) { // send off work for executor 2585 adders[r] = new( matrix[r], cols, &subtotal[r] ); 2586 executor.send( *adders[r] ); 2587 } 2588 for ( r; rows ) { // wait for results 2589 delete( adders[r] ); 2590 total += subtotals[r]; 2591 } 2592 sout | total; 2593 } 2594 \end{cfa} 2595 \end{tabular} 2596 \caption{Executor} 2597 \end{figure} 2598 \end{comment} 2546 2599 2547 2600 … … 2567 2620 The purpose of a cluster is to control the amount of parallelism that is possible among threads, plus scheduling and other execution defaults. 2568 2621 The default cluster-scheduler is single-queue multi-server, which provides automatic load-balancing of threads on processors. 2569 However, the scheduler is pluggable, supporting alternative schedulers, such as multi-queue multi-server,with work-stealing/sharing across the virtual processors.2622 However, the design allows changing the scheduler, \eg multi-queue multi-server with work-stealing/sharing across the virtual processors. 2570 2623 If several clusters exist, both threads and virtual processors, can be explicitly migrated from one cluster to another. 2571 2624 No automatic load balancing among clusters is performed by \CFA. … … 2574 2627 The user cluster is created to contain the application user-threads. 2575 2628 Having all threads execute on the one cluster often maximizes utilization of processors, which minimizes runtime. 2576 However, because of limitations of the underlying operating system, heterogeneous hardware, or scheduling requirements (real-time), multiple clusters are sometimes necessary.2629 However, because of limitations of scheduling requirements (real-time), NUMA architecture, heterogeneous hardware, or issues with the underlying operating system, multiple clusters are sometimes necessary. 2577 2630 2578 2631 … … 2618 2671 \subsection{Preemption} 2619 2672 2620 Nondeterministic preemption provides fairness from long running threads, and forces concurrent programmers to write more robust programs, rather than relying on section of code between cooperative scheduling to be atomic. 2621 A separate reason for not supporting preemption is that it significantly complicates the runtime system. 2673 Nondeterministic preemption provides fairness from long running threads, and forces concurrent programmers to write more robust programs, rather than relying on code between cooperative scheduling to be atomic. 2674 This atomic reliance can fail on multi-core machines, because execution across cores is nondeterministic. 2675 A different reason for not supporting preemption is that it significantly complicates the runtime system, \eg Microsoft runtime does not support interrupts and on Linux systems, interrupts are complex (see below). 2622 2676 Preemption is normally handled by setting a count-down timer on each virtual processor. 2623 2677 When the timer expires, an interrupt is delivered, and the interrupt handler resets the count-down timer, and if the virtual processor is executing in user code, the signal handler performs a user-level context-switch, or if executing in the language runtime-kernel, the preemption is ignored or rolled forward to the point where the runtime kernel context switches back to user code. … … 2628 2682 Because preemption frequency is usually long (1 millisecond) performance cost is negligible. 2629 2683 2630 However, on current Linux systems: 2684 Linux switched a decade ago from specific to arbitrary process signal-delivery for applications with multiple kernel threads. 2631 2685 \begin{cquote} 2632 2686 A process-directed signal may be delivered to any one of the threads that does not currently have the signal blocked. … … 2634 2688 SIGNAL(7) - Linux Programmer's Manual 2635 2689 \end{cquote} 2636 Hence, the timer-expiry signal, which is generated \emph{externally} by the Linux kernel to the Linux process, is delivered to any of its Linux subprocesses (kernel threads).2637 To ensure each virtual processor receives its own preemption signals, a discrete-event simulation is run on a special virtual processor, and only it sets and receives timer events.2690 Hence, the timer-expiry signal, which is generated \emph{externally} by the Linux kernel to an application, is delivered to any of its Linux subprocesses (kernel threads). 2691 To ensure each virtual processor receives a preemption signal, a discrete-event simulation is run on a special virtual processor, and only it sets and receives timer events. 2638 2692 Virtual processors register an expiration time with the discrete-event simulator, which is inserted in sorted order. 2639 2693 The simulation sets the count-down timer to the value at the head of the event list, and when the timer expires, all events less than or equal to the current time are processed. … … 2652 2706 2653 2707 To verify the implementation of the \CFA runtime, a series of microbenchmarks are performed comparing \CFA with Java OpenJDK-9, Go 1.9.2 and \uC 7.0.0. 2654 The benchmark computer is an AMD Opteron\texttrademark\ 6380 NUMA 64-core, 8 socket, 2.5 GHz processor, running Ubuntu 16.04. 3 LTS and \uC and \CFA are compiled with gcc 6.3.2708 The benchmark computer is an AMD Opteron\texttrademark\ 6380 NUMA 64-core, 8 socket, 2.5 GHz processor, running Ubuntu 16.04.6 LTS, and \uC/\CFA are compiled with gcc 6.5. 2655 2709 2656 2710 \begin{comment} … … 2707 2761 \lstset{language=CFA,moredelim=**[is][\color{red}]{@}{@},deletedelim=**[is][]{`}{`}} 2708 2762 \begin{cfa} 2709 threadMyThread {};2710 void main( MyThread & ) {}2763 @thread@ MyThread {}; 2764 void @main@( MyThread & ) {} 2711 2765 int main() { 2712 2766 BENCH( for ( N ) { @MyThread m;@ } ) … … 2750 2804 \lstset{language=CFA,moredelim=**[is][\color{red}]{@}{@},deletedelim=**[is][]{`}{`}} 2751 2805 \begin{cfa}[aboveskip=0pt,belowskip=0pt] 2752 coroutineC {} c;2806 @coroutine@ C {} c; 2753 2807 void main( C & ) { for ( ;; ) { @suspend;@ } } 2754 2808 int main() { // coroutine test … … 2771 2825 \begin{tabular}{@{}r*{3}{D{.}{.}{3.2}}@{}} 2772 2826 \multicolumn{1}{@{}c}{} & \multicolumn{1}{c}{Median} &\multicolumn{1}{c}{Average} & \multicolumn{1}{c@{}}{Std Dev} \\ 2773 Kernel Thread & 333.5 & 332.96 & 4.1 \\ 2827 C function & 2 & 2 & 0 \\ 2828 \CFA generator & 2 & 2 & 0 \\ 2774 2829 \CFA Coroutine & 49 & 48.68 & 0.47 \\ 2775 2830 \CFA Thread & 105 & 105.57 & 1.37 \\ … … 2777 2832 \uC Thread & 100 & 99.29 & 0.96 \\ 2778 2833 Goroutine & 145 & 147.25 & 4.15 \\ 2779 Java Thread & 373.5 & 375.14 & 8.72 2834 Java Thread & 373.5 & 375.14 & 8.72 \\ 2835 Pthreads Thread & 333.5 & 332.96 & 4.1 2780 2836 \end{tabular} 2781 2837 \end{multicols} … … 2793 2849 \lstset{language=CFA,moredelim=**[is][\color{red}]{@}{@},deletedelim=**[is][]{`}{`}} 2794 2850 \begin{cfa} 2795 monitorM {} m1/*, m2, m3, m4*/;2851 @monitor@ M {} m1/*, m2, m3, m4*/; 2796 2852 void __attribute__((noinline)) 2797 do_call( M & mutex m/*, m2, m3, m4*/) {}2853 do_call( M & @mutex m/*, m2, m3, m4*/@ ) {} 2798 2854 int main() { 2799 2855 BENCH( 2800 for( N ) @do_call( m1/*, m2, m3, m4*/ );@2856 for( N ) do_call( m1/*, m2, m3, m4*/ ); 2801 2857 ) 2802 2858 sout | result`ns; … … 2813 2869 \begin{tabular}{@{}r*{3}{D{.}{.}{3.2}}@{}} 2814 2870 \multicolumn{1}{@{}c}{} & \multicolumn{1}{c}{Median} &\multicolumn{1}{c}{Average} & \multicolumn{1}{c@{}}{Std Dev} \\ 2815 C function & 2 & 2 & 0 \\ 2816 FetchAdd + FetchSub & 26 & 26 & 0 \\ 2871 test and test-and-test lock & 26 & 26 & 0 \\ 2817 2872 Pthreads Mutex Lock & 31 & 31.71 & 0.97 \\ 2818 2873 \uC @monitor@ member rtn. & 31 & 31 & 0 \\ … … 2820 2875 \CFA @mutex@ function, 2 arg. & 84 & 85.36 & 1.99 \\ 2821 2876 \CFA @mutex@ function, 4 arg. & 158 & 161 & 4.22 \\ 2822 Java synchronized function& 27.5 & 29.79 & 2.932877 Java synchronized method & 27.5 & 29.79 & 2.93 2823 2878 \end{tabular} 2824 2879 \end{multicols} … … 2836 2891 \begin{cfa} 2837 2892 volatile int go = 0; 2838 monitor M { condition c;} m;2893 @monitor@ M { @condition c;@ } m; 2839 2894 void __attribute__((noinline)) 2840 do_call( M & mutexa1 ) { @signal( c );@ }2895 do_call( M & @mutex@ a1 ) { @signal( c );@ } 2841 2896 thread T {}; 2842 2897 void main( T & this ) { … … 2869 2924 \multicolumn{1}{@{}c}{} & \multicolumn{1}{c}{Median} & \multicolumn{1}{c}{Average} & \multicolumn{1}{c@{}}{Std Dev} \\ 2870 2925 Pthreads Cond. Variable & 6005 & 5681.43 & 835.45 \\ 2871 \uC @signal@ & 324 & 325.54 & 3 ,02 \\2926 \uC @signal@ & 324 & 325.54 & 3.02 \\ 2872 2927 \CFA @signal@, 1 @monitor@ & 368.5 & 370.61 & 4.77 \\ 2873 2928 \CFA @signal@, 2 @monitor@ & 467 & 470.5 & 6.79 \\ … … 2889 2944 \begin{cfa} 2890 2945 volatile int go = 0; 2891 monitorM {} m;2946 @monitor@ M {} m; 2892 2947 thread T {}; 2893 2948 void __attribute__((noinline)) 2894 do_call( M & mutex) {}2949 do_call( M & @mutex@ ) {} 2895 2950 void main( T & ) { 2896 2951 while ( go == 0 ) { yield(); } 2897 while ( go == 1 ) { @do_call( m );@}2952 while ( go == 1 ) { do_call( m ); } 2898 2953 } 2899 2954 int __attribute__((noinline)) 2900 do_wait( M & mutexm ) {2955 do_wait( M & @mutex@ m ) { 2901 2956 go = 1; // continue other thread 2902 2957 BENCH( for ( N ) { @waitfor( do_call, m );@ } ) -
doc/papers/concurrency/annex/local.bib
r18e683b rc1ea11b 66 66 } 67 67 68 @ article{BankTransfer,68 @misc{BankTransfer, 69 69 key = {Bank Transfer}, 70 70 keywords = {Bank Transfer}, 71 71 title = {Bank Account Transfer Problem}, 72 publisher = {Wiki Wiki Web}, 73 address = {http://wiki.c2.com}, 72 howpublished = {Wiki Wiki Web, \url{http://wiki.c2.com/?BankAccountTransferProblem}}, 74 73 year = 2010 75 74 } -
doc/papers/concurrency/examples/Fib.cfa
r18e683b rc1ea11b 13 13 } 14 14 15 #define FibCtor { 0, 1}16 typedef struct { int fn , fn1; } Fib;17 int fib_state( Fib & f ) with( f) {18 int fn0 = fn1 + fn2; fn2 = fn1; fn = fn0;19 return fn1;15 #define FibCtor { 1, 0 } 16 typedef struct { int fn1, fn; } Fib; 17 int fib_state( Fib & f ) with(f) { 18 int ret = fn; fn = fn1; fn1 = fn + ret; 19 return ret; 20 20 } 21 21 … … 32 32 coroutine Fib2 { int fn; }; // used for communication 33 33 void main( Fib2 & fib ) with( fib ) { // called on first resume 34 int fn1 = 1, fn2 = 0; // precompute first two states 34 int fn1; // precompute first two states 35 [fn1, fn] = [1, 0]; 35 36 for () { 36 fn = fn1 + fn2; fn2 = fn1; fn1 = fn; // general case37 37 suspend(); // restart last resume 38 [fn1, fn] = [fn, fn + fn1]; 38 39 } 39 40 } 40 int ?()( Fib2 & fib ) with( fib ) {41 int ?()( Fib2 & fib ) { // function-call interface 41 42 return resume( fib ).fn; // restart last suspend 42 43 } 43 int ?()( Fib2 & fib, int N ) with( fib ) {44 for ( N - 1 ) fib(); 44 int ?()( Fib2 & fib, int N ) { // skip N values 45 for ( N - 1 ) fib(); // use function-call interface 45 46 return fib(); 46 47 } 47 double ?()( Fib2 & fib ) with( fib ) {48 return (int)(fib()) / 3.14159; // restart last suspend48 double ?()( Fib2 & fib ) { // different return type 49 return (int)(fib()) / 3.14159; // cast prevents recursive call 49 50 } 50 51 -
doc/user/user.tex
r18e683b rc1ea11b 11 11 %% Created On : Wed Apr 6 14:53:29 2016 12 12 %% Last Modified By : Peter A. Buhr 13 %% Last Modified On : S un May 5 18:24:50201914 %% Update Count : 3 48913 %% Last Modified On : Sat Jun 15 16:29:45 2019 14 %% Update Count : 3847 15 15 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 16 16 … … 254 254 \begin{lstlisting} 255 255 ®forall( otype T )® T identity( T val ) { return val; } 256 int forty_two = identity( 42 ); 256 int forty_two = identity( 42 ); §\C{// T is bound to int, forty\_two == 42}§ 257 257 \end{lstlisting} 258 258 % extending the C type system with parametric polymorphism and overloading, as opposed to the \Index*[C++]{\CC{}} approach of object-oriented extensions. … … 282 282 283 283 double key = 5.0, vals[10] = { /* 10 sorted floating values */ }; 284 double * val = (double *)bsearch( &key, vals, 10, sizeof(vals[0]), comp ); 284 double * val = (double *)bsearch( &key, vals, 10, sizeof(vals[0]), comp ); §\C{// search sorted array}§ 285 285 \end{lstlisting} 286 286 which can be augmented simply with a polymorphic, type-safe, \CFA-overloaded wrappers: … … 291 291 292 292 forall( otype T | { int ?<?( T, T ); } ) unsigned int bsearch( T key, const T * arr, size_t size ) { 293 T * result = bsearch( key, arr, size ); 294 return result ? result - arr : size; } 295 296 double * val = bsearch( 5.0, vals, 10 ); 293 T * result = bsearch( key, arr, size ); §\C{// call first version}§ 294 return result ? result - arr : size; } §\C{// pointer subtraction includes sizeof(T)}§ 295 296 double * val = bsearch( 5.0, vals, 10 ); §\C{// selection based on return type}§ 297 297 int posn = bsearch( 5.0, vals, 10 ); 298 298 \end{lstlisting} … … 306 306 \begin{lstlisting} 307 307 forall( dtype T | sized(T) ) T * malloc( void ) { return (T *)malloc( sizeof(T) ); } 308 int * ip = malloc(); 308 int * ip = malloc(); §\C{// select type and size from left-hand side}§ 309 309 double * dp = malloc(); 310 310 struct S {...} * sp = malloc(); … … 318 318 \begin{cfa} 319 319 char ®abs®( char ); 320 extern "C" { int ®abs®( int ); } 320 extern "C" { int ®abs®( int ); } §\C{// use default C routine for int}§ 321 321 long int ®abs®( long int ); 322 322 long long int ®abs®( long long int ); … … 426 426 \begin{cfa} 427 427 #ifndef __CFORALL__ 428 #include <stdio.h>§\indexc{stdio.h}§ 428 #include <stdio.h>§\indexc{stdio.h}§ §\C{// C header file}§ 429 429 #else 430 #include <fstream>§\indexc{fstream}§ 430 #include <fstream>§\indexc{fstream}§ §\C{// \CFA header file}§ 431 431 #endif 432 432 \end{cfa} … … 512 512 Keyword clashes are accommodated by syntactic transformations using the \CFA backquote escape-mechanism: 513 513 \begin{cfa} 514 int ®`®otype®`® = 3; 514 int ®`®otype®`® = 3; §\C{// make keyword an identifier}§ 515 515 double ®`®forall®`® = 3.5; 516 516 \end{cfa} … … 523 523 \begin{cfa} 524 524 // include file uses the CFA keyword "with". 525 #if ! defined( with ) 526 #define with ®`®with®`® 525 #if ! defined( with ) §\C{// nesting ?}§ 526 #define with ®`®with®`® §\C{// make keyword an identifier}§ 527 527 #define __CFA_BFD_H__ 528 528 #endif 529 529 530 ®#include_next <bfdlink.h> 530 ®#include_next <bfdlink.h> §\C{// must have internal check for multiple expansion}§ 531 531 ® 532 532 #if defined( with ) && defined( __CFA_BFD_H__ ) §\C{// reset only if set}§ … … 544 544 Numeric constants are extended to allow \Index{underscore}s\index{constant!underscore}, \eg: 545 545 \begin{cfa} 546 2®_®147®_®483®_®648; 547 56®_®ul; 548 0®_®377; 549 0x®_®ff®_®ff; 550 0x®_®ef3d®_®aa5c; 551 3.141®_®592®_®654; 552 10®_®e®_®+1®_®00; 553 0x®_®ff®_®ff®_®p®_®3; 554 0x®_®1.ffff®_®ffff®_®p®_®128®_®l; 555 L®_®§"\texttt{\textbackslash{x}}§®_®§\texttt{ff}§®_®§\texttt{ee}"§; 546 2®_®147®_®483®_®648; §\C{// decimal constant}§ 547 56®_®ul; §\C{// decimal unsigned long constant}§ 548 0®_®377; §\C{// octal constant}§ 549 0x®_®ff®_®ff; §\C{// hexadecimal constant}§ 550 0x®_®ef3d®_®aa5c; §\C{// hexadecimal constant}§ 551 3.141®_®592®_®654; §\C{// floating constant}§ 552 10®_®e®_®+1®_®00; §\C{// floating constant}§ 553 0x®_®ff®_®ff®_®p®_®3; §\C{// hexadecimal floating}§ 554 0x®_®1.ffff®_®ffff®_®p®_®128®_®l; §\C{// hexadecimal floating long constant}§ 555 L®_®§"\texttt{\textbackslash{x}}§®_®§\texttt{ff}§®_®§\texttt{ee}"§; §\C{// wide character constant}§ 556 556 \end{cfa} 557 557 The rules for placement of underscores are: … … 612 612 (Does not make sense for ©do©-©while©.) 613 613 \begin{cfa} 614 if ( ®int x = f()® ) ... 615 if ( ®int x = f(), y = g()® ) ... 616 if ( ®int x = f(), y = g(); x < y® ) ... 614 if ( ®int x = f()® ) ... §\C{// x != 0}§ 615 if ( ®int x = f(), y = g()® ) ... §\C{// x != 0 \&\& y != 0}§ 616 if ( ®int x = f(), y = g(); x < y® ) ... §\C{// relational expression}§ 617 617 if ( ®struct S { int i; } x = { f() }; x.i < 4® ) §\C{// relational expression}§ 618 618 619 while ( ®int x = f()® ) ... 620 while ( ®int x = f(), y = g()® ) ... 619 while ( ®int x = f()® ) ... §\C{// x != 0}§ 620 while ( ®int x = f(), y = g()® ) ... §\C{// x != 0 \&\& y != 0}§ 621 621 while ( ®int x = f(), y = g(); x < y® ) ... §\C{// relational expression}§ 622 622 while ( ®struct S { int i; } x = { f() }; x.i < 4® ) ... §\C{// relational expression}§ … … 892 892 \begin{cfa} 893 893 switch ( x ) { 894 ®int y = 1;® 895 ®x = 7;® 894 ®int y = 1;® §\C{// unreachable initialization}§ 895 ®x = 7;® §\C{// unreachable code without label/branch}§ 896 896 case 0: ... 897 897 ... 898 ®int z = 0;® 898 ®int z = 0;® §\C{// unreachable initialization, cannot appear after case}§ 899 899 z = 2; 900 900 case 1: 901 ®x = z;® 901 ®x = z;® §\C{// without fall through, z is uninitialized}§ 902 902 } 903 903 \end{cfa} … … 937 937 ®case 5: 938 938 ... 939 ®fallthru®; 939 ®fallthru®; §\C{// explicit fall through}§ 940 940 case 7: 941 941 ... 942 ®break® 942 ®break® §\C{// explicit end of switch (redundant)}§ 943 943 default: 944 944 j = 3; … … 961 961 \begin{cfa} 962 962 switch ( x ) { 963 ®int i = 0;® 963 ®int i = 0;® §\C{// allowed only at start}§ 964 964 case 0: 965 965 ... 966 ®int j = 0;® 966 ®int j = 0;® §\C{// disallowed}§ 967 967 case 1: 968 968 { 969 ®int k = 0;® 969 ®int k = 0;® §\C{// allowed at different nesting levels}§ 970 970 ... 971 ®case 2:® 971 ®case 2:® §\C{// disallow case in nested statements}§ 972 972 } 973 973 ... … … 1019 1019 \begin{cfa} 1020 1020 switch ( i ) { 1021 case ®1~5:® 1021 case ®1~5:® §\C{// 1, 2, 3, 4, 5}§ 1022 1022 ... 1023 case ®10~15:® 1023 case ®10~15:® §\C{// 10, 11, 12, 13, 14, 15}§ 1024 1024 ... 1025 1025 } … … 1152 1152 Grouping heterogeneous data into \newterm{aggregate}s (structure/union) is a common programming practice, and an aggregate can be further organized into more complex structures, such as arrays and containers: 1153 1153 \begin{cfa} 1154 struct S { 1155 char c; 1154 struct S { §\C{// aggregate}§ 1155 char c; §\C{// fields}§ 1156 1156 int i; 1157 1157 double d; … … 1162 1162 \begin{cfa} 1163 1163 void f( S s ) { 1164 ®s.®c; ®s.®i; ®s.®d; 1164 ®s.®c; ®s.®i; ®s.®d; §\C{// access containing fields}§ 1165 1165 } 1166 1166 \end{cfa} … … 1169 1169 \begin{C++} 1170 1170 struct S { 1171 char c; 1171 char c; §\C{// fields}§ 1172 1172 int i; 1173 1173 double d; 1174 void f() { 1175 ®this->®c; ®this->®i; ®this->®d; 1174 void f() { §\C{// implicit ``this'' aggregate}§ 1175 ®this->®c; ®this->®i; ®this->®d; §\C{// access containing fields}§ 1176 1176 } 1177 1177 } … … 1181 1181 \begin{cfa} 1182 1182 struct T { double m, n; }; 1183 int S::f( T & t ) { 1184 c; i; d; 1185 ®t.®m; ®t.®n; 1183 int S::f( T & t ) { §\C{// multiple aggregate parameters}§ 1184 c; i; d; §\C{\color{red}// this--{\textgreater}.c, this--{\textgreater}.i, this--{\textgreater}.d}§ 1185 ®t.®m; ®t.®n; §\C{// must qualify}§ 1186 1186 } 1187 1187 \end{cfa} … … 1190 1190 Hence, the qualified fields become variables with the side-effect that it is easier to optimizing field references in a block. 1191 1191 \begin{cfa} 1192 void f( S & this ) ®with ( this )® { 1193 c; i; d; 1192 void f( S & this ) ®with ( this )® { §\C{// with statement}§ 1193 c; i; d; §\C{\color{red}// this.c, this.i, this.d}§ 1194 1194 } 1195 1195 \end{cfa} 1196 1196 with the generality of opening multiple aggregate-parameters: 1197 1197 \begin{cfa} 1198 void f( S & s, T & t ) ®with ( s, t )® { 1199 c; i; d; 1200 m; n; 1198 void f( S & s, T & t ) ®with ( s, t )® { §\C{// multiple aggregate parameters}§ 1199 c; i; d; §\C{\color{red}// s.c, s.i, s.d}§ 1200 m; n; §\C{\color{red}// t.m, t.n}§ 1201 1201 } 1202 1202 \end{cfa} … … 1220 1220 struct T { int ®i®; int k; int m; } t, w; 1221 1221 with ( s, t ) { 1222 j + k; 1223 m = 5.0; 1224 m = 1; 1225 int a = m; 1226 double b = m; 1227 int c = s.i + t.i; 1228 (double)m; 1222 j + k; §\C{// unambiguous, s.j + t.k}§ 1223 m = 5.0; §\C{// unambiguous, t.m = 5.0}§ 1224 m = 1; §\C{// unambiguous, s.m = 1}§ 1225 int a = m; §\C{// unambiguous, a = s.i }§ 1226 double b = m; §\C{// unambiguous, b = t.m}§ 1227 int c = s.i + t.i; §\C{// unambiguous, qualification}§ 1228 (double)m; §\C{// unambiguous, cast}§ 1229 1229 } 1230 1230 \end{cfa} … … 1236 1236 There is an interesting problem between parameters and the function-body ©with©, \eg: 1237 1237 \begin{cfa} 1238 void ?{}( S & s, int i ) with ( s ) { 1239 ®s.i = i;® j = 3; m = 5.5; 1238 void ?{}( S & s, int i ) with ( s ) { §\C{// constructor}§ 1239 ®s.i = i;® j = 3; m = 5.5; §\C{// initialize fields}§ 1240 1240 } 1241 1241 \end{cfa} … … 1256 1256 Finally, a cast may be used to disambiguate among overload variables in a ©with© expression: 1257 1257 \begin{cfa} 1258 with ( w ) { ... } 1259 with ( (S)w ) { ... } 1258 with ( w ) { ... } §\C{// ambiguous, same name and no context}§ 1259 with ( (S)w ) { ... } §\C{// unambiguous, cast}§ 1260 1260 \end{cfa} 1261 1261 and ©with© expressions may be complex expressions with type reference (see Section~\ref{s:References}) to aggregate: 1262 1262 % \begin{cfa} 1263 1263 % struct S { int i, j; } sv; 1264 % with ( sv ) { 1264 % with ( sv ) { §\C{// implicit reference}§ 1265 1265 % S & sr = sv; 1266 % with ( sr ) { 1266 % with ( sr ) { §\C{// explicit reference}§ 1267 1267 % S * sp = &sv; 1268 % with ( *sp ) { 1269 % i = 3; j = 4; 1268 % with ( *sp ) { §\C{// computed reference}§ 1269 % i = 3; j = 4; §\C{\color{red}// sp--{\textgreater}i, sp--{\textgreater}j}§ 1270 1270 % } 1271 % i = 2; j = 3; 1271 % i = 2; j = 3; §\C{\color{red}// sr.i, sr.j}§ 1272 1272 % } 1273 % i = 1; j = 2; 1273 % i = 1; j = 2; §\C{\color{red}// sv.i, sv.j}§ 1274 1274 % } 1275 1275 % \end{cfa} … … 1279 1279 class C { 1280 1280 int i, j; 1281 int mem() { 1282 i = 1; 1283 j = 2; 1281 int mem() { §\C{\color{red}// implicit "this" parameter}§ 1282 i = 1; §\C{\color{red}// this->i}§ 1283 j = 2; §\C{\color{red}// this->j}§ 1284 1284 } 1285 1285 } … … 1288 1288 \begin{cfa} 1289 1289 struct S { int i, j; }; 1290 int mem( S & ®this® ) { 1291 ®this.®i = 1; 1290 int mem( S & ®this® ) { §\C{// explicit "this" parameter}§ 1291 ®this.®i = 1; §\C{// "this" is not elided}§ 1292 1292 ®this.®j = 2; 1293 1293 } … … 1297 1297 \CFA provides a ©with© clause/statement (see Pascal~\cite[\S~4.F]{Pascal}) to elided the "©this.©" by opening a scope containing field identifiers, changing the qualified fields into variables and giving an opportunity for optimizing qualified references. 1298 1298 \begin{cfa} 1299 int mem( S & this ) ®with( this )® { 1300 i = 1; 1301 j = 2; 1299 int mem( S & this ) ®with( this )® { §\C{// with clause}§ 1300 i = 1; §\C{\color{red}// this.i}§ 1301 j = 2; §\C{\color{red}// this.j}§ 1302 1302 } 1303 1303 \end{cfa} … … 1316 1316 struct S1 { ... } s1; 1317 1317 struct S2 { ... } s2; 1318 ®with( s1 )® { 1318 ®with( s1 )® { §\C{// with statement}§ 1319 1319 // access fields of s1 without qualification 1320 ®with s2® { 1320 ®with s2® { §\C{// nesting}§ 1321 1321 // access fields of s1 and s2 without qualification 1322 1322 } … … 1373 1373 Non-local transfer can cause stack unwinding, \ie non-local routine termination, depending on the kind of raise. 1374 1374 \begin{cfa} 1375 exception_t E {}; 1375 exception_t E {}; §\C{// exception type}§ 1376 1376 void f(...) { 1377 ... throw E{}; ... 1378 ... throwResume E{}; ... 1377 ... throw E{}; ... §\C{// termination}§ 1378 ... throwResume E{}; ... §\C{// resumption}§ 1379 1379 } 1380 1380 try { … … 1442 1442 For example, a routine returning a \Index{pointer} to an array of integers is defined and used in the following way: 1443 1443 \begin{cfa} 1444 int ®(*®f®())[®5®]® {...}; 1445 ... ®(*®f®())[®3®]® += 1; 1444 int ®(*®f®())[®5®]® {...}; §\C{// definition}§ 1445 ... ®(*®f®())[®3®]® += 1; §\C{// usage}§ 1446 1446 \end{cfa} 1447 1447 Essentially, the return type is wrapped around the routine name in successive layers (like an \Index{onion}). … … 1635 1635 *x = 3; // implicit dereference 1636 1636 int * ®const® y = (int *)104; 1637 *y = *x; // implicit dereference1637 *y = *x; // implicit dereference 1638 1638 \end{cfa} 1639 1639 \end{tabular} … … 1649 1649 \hline 1650 1650 \begin{cfa} 1651 lda r1,100 1652 ld r2,(r1) 1653 lda r3,104 1654 st r2,(r3) 1651 lda r1,100 // load address of x 1652 ld r2,(r1) // load value of x 1653 lda r3,104 // load address of y 1654 st r2,(r3) // store x into y 1655 1655 \end{cfa} 1656 1656 & 1657 1657 \begin{cfa} 1658 1658 1659 ld r2,(100) 1660 1661 st r2,(104) 1659 ld r2,(100) // load value of x 1660 1661 st r2,(104) // store x into y 1662 1662 \end{cfa} 1663 1663 \end{tabular} … … 1673 1673 \begin{cfa} 1674 1674 int x, y, ®*® p1, ®*® p2, ®**® p3; 1675 p1 = ®&®x; 1676 p2 = p1; 1677 p1 = ®&®y; 1678 p3 = &p2; 1675 p1 = ®&®x; // p1 points to x 1676 p2 = p1; // p2 points to x 1677 p1 = ®&®y; // p1 points to y 1678 p3 = &p2; // p3 points to p2 1679 1679 \end{cfa} 1680 1680 & … … 1687 1687 For example, \Index*{Algol68}~\cite{Algol68} infers pointer dereferencing to select the best meaning for each pointer usage 1688 1688 \begin{cfa} 1689 p2 = p1 + x; 1689 p2 = p1 + x; §\C{// compiler infers *p2 = *p1 + x;}§ 1690 1690 \end{cfa} 1691 1691 Algol68 infers the following dereferencing ©*p2 = *p1 + x©, because adding the arbitrary integer value in ©x© to the address of ©p1© and storing the resulting address into ©p2© is an unlikely operation. … … 1695 1695 In C, objects of pointer type always manipulate the pointer object's address: 1696 1696 \begin{cfa} 1697 p1 = p2; 1698 p2 = p1 + x; 1697 p1 = p2; §\C{// p1 = p2\ \ rather than\ \ *p1 = *p2}§ 1698 p2 = p1 + x; §\C{// p2 = p1 + x\ \ rather than\ \ *p2 = *p1 + x}§ 1699 1699 \end{cfa} 1700 1700 even though the assignment to ©p2© is likely incorrect, and the programmer probably meant: 1701 1701 \begin{cfa} 1702 p1 = p2; 1703 ®*®p2 = ®*®p1 + x; 1702 p1 = p2; §\C{// pointer address assignment}§ 1703 ®*®p2 = ®*®p1 + x; §\C{// pointed-to value assignment / operation}§ 1704 1704 \end{cfa} 1705 1705 The C semantics work well for situations where manipulation of addresses is the primary meaning and data is rarely accessed, such as storage management (©malloc©/©free©). … … 1718 1718 \begin{cfa} 1719 1719 int x, y, ®&® r1, ®&® r2, ®&&® r3; 1720 ®&®r1 = &x; 1721 ®&®r2 = &r1; 1722 ®&®r1 = &y; 1723 ®&&®r3 = ®&®&r2; 1720 ®&®r1 = &x; §\C{// r1 points to x}§ 1721 ®&®r2 = &r1; §\C{// r2 points to x}§ 1722 ®&®r1 = &y; §\C{// r1 points to y}§ 1723 ®&&®r3 = ®&®&r2; §\C{// r3 points to r2}§ 1724 1724 r2 = ((r1 + r2) * (r3 - r1)) / (r3 - 15); §\C{// implicit dereferencing}§ 1725 1725 \end{cfa} … … 1737 1737 For a \CFA reference type, the cancellation on the left-hand side of assignment leaves the reference as an address (\Index{lvalue}): 1738 1738 \begin{cfa} 1739 (&®*®)r1 = &x; 1739 (&®*®)r1 = &x; §\C{// (\&*) cancel giving address in r1 not variable pointed-to by r1}§ 1740 1740 \end{cfa} 1741 1741 Similarly, the address of a reference can be obtained for assignment or computation (\Index{rvalue}): 1742 1742 \begin{cfa} 1743 (&(&®*®)®*®)r3 = &(&®*®)r2; 1743 (&(&®*®)®*®)r3 = &(&®*®)r2; §\C{// (\&*) cancel giving address in r2, (\&(\&*)*) cancel giving address in r3}§ 1744 1744 \end{cfa} 1745 1745 Cancellation\index{cancellation!pointer/reference}\index{pointer!cancellation} works to arbitrary depth. … … 1749 1749 int x, *p1 = &x, **p2 = &p1, ***p3 = &p2, 1750 1750 &r1 = x, &&r2 = r1, &&&r3 = r2; 1751 ***p3 = 3; 1752 r3 = 3; 1753 **p3 = ...; 1754 &r3 = ...; 1755 *p3 = ...; 1756 &&r3 = ...; 1757 &&&r3 = p3; 1751 ***p3 = 3; §\C{// change x}§ 1752 r3 = 3; §\C{// change x, ***r3}§ 1753 **p3 = ...; §\C{// change p1}§ 1754 &r3 = ...; §\C{// change r1, (\&*)**r3, 1 cancellation}§ 1755 *p3 = ...; §\C{// change p2}§ 1756 &&r3 = ...; §\C{// change r2, (\&(\&*)*)*r3, 2 cancellations}§ 1757 &&&r3 = p3; §\C{// change r3 to p3, (\&(\&(\&*)*)*)r3, 3 cancellations}§ 1758 1758 \end{cfa} 1759 1759 Furthermore, both types are equally performant, as the same amount of dereferencing occurs for both types. … … 1762 1762 As for a pointer type, a reference type may have qualifiers: 1763 1763 \begin{cfa} 1764 const int cx = 5; 1765 const int & cr = cx; 1766 ®&®cr = &cx; 1767 cr = 7; 1768 int & const rc = x; 1769 ®&®rc = &x; 1770 const int & const crc = cx; 1771 crc = 7; 1772 ®&®crc = &cx; 1764 const int cx = 5; §\C{// cannot change cx;}§ 1765 const int & cr = cx; §\C{// cannot change what cr points to}§ 1766 ®&®cr = &cx; §\C{// can change cr}§ 1767 cr = 7; §\C{// error, cannot change cx}§ 1768 int & const rc = x; §\C{// must be initialized}§ 1769 ®&®rc = &x; §\C{// error, cannot change rc}§ 1770 const int & const crc = cx; §\C{// must be initialized}§ 1771 crc = 7; §\C{// error, cannot change cx}§ 1772 ®&®crc = &cx; §\C{// error, cannot change crc}§ 1773 1773 \end{cfa} 1774 1774 Hence, for type ©& const©, there is no pointer assignment, so ©&rc = &x© is disallowed, and \emph{the address value cannot be the null pointer unless an arbitrary pointer is coerced\index{coercion} into the reference}: 1775 1775 \begin{cfa} 1776 int & const cr = *0; 1776 int & const cr = *0; §\C{// where 0 is the int * zero}§ 1777 1777 \end{cfa} 1778 1778 Note, constant reference-types do not prevent \Index{addressing errors} because of explicit storage-management: … … 1781 1781 cr = 5; 1782 1782 free( &cr ); 1783 cr = 7; 1783 cr = 7; §\C{// unsound pointer dereference}§ 1784 1784 \end{cfa} 1785 1785 … … 1806 1806 \begin{cfa} 1807 1807 int w, x, y, z, & ar[3] = { x, y, z }; §\C{// initialize array of references}§ 1808 &ar[1] = &w; 1809 typeof( ar[1] ) p; 1810 typeof( &ar[1] ) q; 1811 sizeof( ar[1] ) == sizeof( int ); 1812 sizeof( &ar[1] ) == sizeof( int *) 1808 &ar[1] = &w; §\C{// change reference array element}§ 1809 typeof( ar[1] ) p; §\C{// (gcc) is int, \ie the type of referenced object}§ 1810 typeof( &ar[1] ) q; §\C{// (gcc) is int \&, \ie the type of reference}§ 1811 sizeof( ar[1] ) == sizeof( int ); §\C{// is true, \ie the size of referenced object}§ 1812 sizeof( &ar[1] ) == sizeof( int *) §\C{// is true, \ie the size of a reference}§ 1813 1813 \end{cfa} 1814 1814 … … 1827 1827 Therefore, for pointer/reference initialization, the initializing value must be an address not a value. 1828 1828 \begin{cfa} 1829 int * p = &x; 1830 ®int * p = x;® 1831 int & r = x; 1829 int * p = &x; §\C{// assign address of x}§ 1830 ®int * p = x;® §\C{// assign value of x}§ 1831 int & r = x; §\C{// must have address of x}§ 1832 1832 \end{cfa} 1833 1833 Like the previous example with C pointer-arithmetic, it is unlikely assigning the value of ©x© into a pointer is meaningful (again, a warning is usually given). … … 1838 1838 Similarly, when a reference type is used for a parameter/return type, the call-site argument does not require a reference operator for the same reason. 1839 1839 \begin{cfa} 1840 int & f( int & r ); 1841 z = f( x ) + f( y ); 1840 int & f( int & r ); §\C{// reference parameter and return}§ 1841 z = f( x ) + f( y ); §\C{// reference operator added, temporaries needed for call results}§ 1842 1842 \end{cfa} 1843 1843 Within routine ©f©, it is possible to change the argument by changing the corresponding parameter, and parameter ©r© can be locally reassigned within ©f©. … … 1866 1866 void f( int & r ); 1867 1867 void g( int * p ); 1868 f( 3 ); g( ®&®3 ); 1869 f( x + y ); g( ®&®(x + y) ); 1868 f( 3 ); g( ®&®3 ); §\C{// compiler implicit generates temporaries}§ 1869 f( x + y ); g( ®&®(x + y) ); §\C{// compiler implicit generates temporaries}§ 1870 1870 \end{cfa} 1871 1871 Essentially, there is an implicit \Index{rvalue} to \Index{lvalue} conversion in this case.\footnote{ … … 1878 1878 \begin{cfa} 1879 1879 void f( int i ); 1880 void (* fp)( int ); 1881 fp = f; 1882 fp = &f; 1883 fp = *f; 1884 fp(3); 1885 (*fp)(3); 1880 void (* fp)( int ); §\C{// routine pointer}§ 1881 fp = f; §\C{// reference initialization}§ 1882 fp = &f; §\C{// pointer initialization}§ 1883 fp = *f; §\C{// reference initialization}§ 1884 fp(3); §\C{// reference invocation}§ 1885 (*fp)(3); §\C{// pointer invocation}§ 1886 1886 \end{cfa} 1887 1887 While C's treatment of routine objects has similarity to inferring a reference type in initialization contexts, the examples are assignment not initialization, and all possible forms of assignment are possible (©f©, ©&f©, ©*f©) without regard for type. 1888 1888 Instead, a routine object should be referenced by a ©const© reference: 1889 1889 \begin{cfa} 1890 ®const® void (®&® fr)( int ) = f; 1891 fr = ... 1892 &fr = ...; 1893 fr( 3 ); 1894 (*fr)(3); 1890 ®const® void (®&® fr)( int ) = f; §\C{// routine reference}§ 1891 fr = ... §\C{// error, cannot change code}§ 1892 &fr = ...; §\C{// changing routine reference}§ 1893 fr( 3 ); §\C{// reference call to f}§ 1894 (*fr)(3); §\C{// error, incorrect type}§ 1895 1895 \end{cfa} 1896 1896 because the value of the routine object is a routine literal, \ie the routine code is normally immutable during execution.\footnote{ … … 1914 1914 int x, * px, ** ppx, *** pppx, **** ppppx; 1915 1915 int & rx = x, && rrx = rx, &&& rrrx = rrx ; 1916 x = rrrx; // rrrx is an lvalue with type int &&& (equivalent to x)1917 px = &rrrx; // starting from rrrx, &rrrx is an rvalue with type int *&&& (&x)1918 ppx = &&rrrx; // starting from &rrrx, &&rrrx is an rvalue with type int **&& (&rx)1919 pppx = &&&rrrx; // starting from &&rrrx, &&&rrrx is an rvalue with type int ***& (&rrx)1920 ppppx = &&&&rrrx; // starting from &&&rrrx, &&&&rrrx is an rvalue with type int **** (&rrrx)1916 x = rrrx; §\C[2.0in]{// rrrx is an lvalue with type int \&\&\& (equivalent to x)}§ 1917 px = &rrrx; §\C{// starting from rrrx, \&rrrx is an rvalue with type int *\&\&\& (\&x)}§ 1918 ppx = &&rrrx; §\C{// starting from \&rrrx, \&\&rrrx is an rvalue with type int **\&\& (\&rx)}§ 1919 pppx = &&&rrrx; §\C{// starting from \&\&rrrx, \&\&\&rrrx is an rvalue with type int ***\& (\&rrx)}§ 1920 ppppx = &&&&rrrx; §\C{// starting from \&\&\&rrrx, \&\&\&\&rrrx is an rvalue with type int **** (\&rrrx)}§ 1921 1921 \end{cfa} 1922 1922 The following example shows the second rule applied to different \Index{lvalue} contexts: … … 1924 1924 int x, * px, ** ppx, *** pppx; 1925 1925 int & rx = x, && rrx = rx, &&& rrrx = rrx ; 1926 rrrx = 2; // rrrx is an lvalue with type int &&& (equivalent to x)1927 &rrrx = px; // starting from rrrx, &rrrx is an rvalue with type int *&&& (rx)1928 &&rrrx = ppx; // starting from &rrrx, &&rrrx is an rvalue with type int **&& (rrx)1929 &&&rrrx = pppx; // starting from &&rrrx, &&&rrrx is an rvalue with type int ***& (rrrx)1926 rrrx = 2; §\C{// rrrx is an lvalue with type int \&\&\& (equivalent to x)}§ 1927 &rrrx = px; §\C{// starting from rrrx, \&rrrx is an rvalue with type int *\&\&\& (rx)}§ 1928 &&rrrx = ppx; §\C{// starting from \&rrrx, \&\&rrrx is an rvalue with type int **\&\& (rrx)}§ 1929 &&&rrrx = pppx; §\C{// starting from \&\&rrrx, \&\&\&rrrx is an rvalue with type int ***\& (rrrx)}\CRT§ 1930 1930 \end{cfa} 1931 1931 … … 1940 1940 \begin{cfa} 1941 1941 int x; 1942 x + 1; // lvalue variable (int) converts to rvalue for expression1942 x + 1; §\C[2.0in]{// lvalue variable (int) converts to rvalue for expression}§ 1943 1943 \end{cfa} 1944 1944 An rvalue has no type qualifiers (©cv©), so the lvalue qualifiers are dropped. … … 1950 1950 \begin{cfa} 1951 1951 int x, &r = x, f( int p ); 1952 x = ®r® + f( ®r® ); // lvalue reference converts to rvalue1952 x = ®r® + f( ®r® ); §\C{// lvalue reference converts to rvalue}§ 1953 1953 \end{cfa} 1954 1954 An rvalue has no type qualifiers (©cv©), so the reference qualifiers are dropped. … … 1957 1957 lvalue to reference conversion: \lstinline[deletekeywords=lvalue]@lvalue-type cv1 T@ converts to ©cv2 T &©, which allows implicitly converting variables to references. 1958 1958 \begin{cfa} 1959 int x, &r = ®x®, f( int & p ); // lvalue variable (int) convert to reference (int &)1960 f( ®x® ); // lvalue variable (int) convert to reference (int &)1959 int x, &r = ®x®, f( int & p ); §\C{// lvalue variable (int) convert to reference (int \&)}§ 1960 f( ®x® ); §\C{// lvalue variable (int) convert to reference (int \&)}§ 1961 1961 \end{cfa} 1962 1962 Conversion can restrict a type, where ©cv1© $\le$ ©cv2©, \eg passing an ©int© to a ©const volatile int &©, which has low cost. … … 1968 1968 \begin{cfa} 1969 1969 int x, & f( int & p ); 1970 f( ®x + 3® ); // rvalue parameter (int) implicitly converts to lvalue temporary reference (int &)1971 ®&f®(...) = &x; // rvalue result (int &) implicitly converts to lvalue temporary reference (int &)1970 f( ®x + 3® ); §\C[1.5in]{// rvalue parameter (int) implicitly converts to lvalue temporary reference (int \&)}§ 1971 ®&f®(...) = &x; §\C{// rvalue result (int \&) implicitly converts to lvalue temporary reference (int \&)}\CRT§ 1972 1972 \end{cfa} 1973 1973 In both case, modifications to the temporary are inaccessible (\Index{warning}). … … 2158 2158 in both cases the type is assumed to be void as opposed to old style C defaults of int return type and unknown parameter types, respectively, as in: 2159 2159 \begin{cfa} 2160 [§\,§] g(); 2161 [ void ] g( void ); 2160 [§\,§] g(); §\C{// no input or output parameters}§ 2161 [ void ] g( void ); §\C{// no input or output parameters}§ 2162 2162 \end{cfa} 2163 2163 … … 2177 2177 \begin{cfa} 2178 2178 typedef int foo; 2179 int f( int (* foo) ); 2179 int f( int (* foo) ); §\C{// foo is redefined as a parameter name}§ 2180 2180 \end{cfa} 2181 2181 The string ``©int (* foo)©'' declares a C-style named-parameter of type pointer to an integer (the parenthesis are superfluous), while the same string declares a \CFA style unnamed parameter of type routine returning integer with unnamed parameter of type pointer to foo. … … 2185 2185 C-style declarations can be used to declare parameters for \CFA style routine definitions, \eg: 2186 2186 \begin{cfa} 2187 [ int ] f( * int, int * ); 2188 [ * int, int * ] f( int ); 2187 [ int ] f( * int, int * ); §\C{// returns an integer, accepts 2 pointers to integers}§ 2188 [ * int, int * ] f( int ); §\C{// returns 2 pointers to integers, accepts an integer}§ 2189 2189 \end{cfa} 2190 2190 The reason for allowing both declaration styles in the new context is for backwards compatibility with existing preprocessor macros that generate C-style declaration-syntax, as in: 2191 2191 \begin{cfa} 2192 2192 #define ptoa( n, d ) int (*n)[ d ] 2193 int f( ptoa( p, 5 ) ) ... 2194 [ int ] f( ptoa( p, 5 ) ) ... 2193 int f( ptoa( p, 5 ) ) ... §\C{// expands to int f( int (*p)[ 5 ] )}§ 2194 [ int ] f( ptoa( p, 5 ) ) ... §\C{// expands to [ int ] f( int (*p)[ 5 ] )}§ 2195 2195 \end{cfa} 2196 2196 Again, programmers are highly encouraged to use one declaration form or the other, rather than mixing the forms. … … 2214 2214 int z; 2215 2215 ... x = 0; ... y = z; ... 2216 ®return;® 2216 ®return;® §\C{// implicitly return x, y}§ 2217 2217 } 2218 2218 \end{cfa} … … 2224 2224 [ int x, int y ] f() { 2225 2225 ... 2226 } 2226 } §\C{// implicitly return x, y}§ 2227 2227 \end{cfa} 2228 2228 In this case, the current values of ©x© and ©y© are returned to the calling routine just as if a ©return© had been encountered. … … 2233 2233 [ int x, int y ] f( int, x, int y ) { 2234 2234 ... 2235 } 2235 } §\C{// implicitly return x, y}§ 2236 2236 \end{cfa} 2237 2237 This notation allows the compiler to eliminate temporary variables in nested routine calls. 2238 2238 \begin{cfa} 2239 [ int x, int y ] f( int, x, int y ); 2239 [ int x, int y ] f( int, x, int y ); §\C{// prototype declaration}§ 2240 2240 int a, b; 2241 2241 [a, b] = f( f( f( a, b ) ) ); … … 2251 2251 as well, parameter names are optional, \eg: 2252 2252 \begin{cfa} 2253 [ int x ] f (); 2254 [ * int ] g (int y); 2255 [ ] h ( int, char ); 2256 [ * int, int ] j ( int ); 2253 [ int x ] f (); §\C{// returning int with no parameters}§ 2254 [ * int ] g (int y); §\C{// returning pointer to int with int parameter}§ 2255 [ ] h ( int, char ); §\C{// returning no result with int and char parameters}§ 2256 [ * int, int ] j ( int ); §\C{// returning pointer to int and int, with int parameter}§ 2257 2257 \end{cfa} 2258 2258 This syntax allows a prototype declaration to be created by cutting and pasting source text from the routine definition header (or vice versa). … … 2275 2275 The syntax for pointers to \CFA routines specifies the pointer name on the right, \eg: 2276 2276 \begin{cfa} 2277 * [ int x ] () fp; 2278 * [ * int ] (int y) gp; 2279 * [ ] (int,char) hp; 2280 * [ * int,int ] ( int ) jp; 2277 * [ int x ] () fp; §\C{// pointer to routine returning int with no parameters}§ 2278 * [ * int ] (int y) gp; §\C{// pointer to routine returning pointer to int with int parameter}§ 2279 * [ ] (int,char) hp; §\C{// pointer to routine returning no result with int and char parameters}§ 2280 * [ * int,int ] ( int ) jp; §\C{// pointer to routine returning pointer to int and int, with int parameter}§ 2281 2281 \end{cfa} 2282 2282 While parameter names are optional, \emph{a routine name cannot be specified}; 2283 2283 for example, the following is incorrect: 2284 2284 \begin{cfa} 2285 * [ int x ] f () fp; 2285 * [ int x ] f () fp; §\C{// routine name "f" is not allowed}§ 2286 2286 \end{cfa} 2287 2287 … … 2306 2306 whereas a named (keyword) call may be: 2307 2307 \begin{cfa} 2308 p( z : 3, x : 4, y : 7 ); 2308 p( z : 3, x : 4, y : 7 ); §\C{// rewrite $\Rightarrow$ p( 4, 7, 3 )}§ 2309 2309 \end{cfa} 2310 2310 Here the order of the arguments is unimportant, and the names of the parameters are used to associate argument values with the corresponding parameters. … … 2323 2323 For example, the following routine prototypes and definition are all valid. 2324 2324 \begin{cfa} 2325 void p( int, int, int ); 2325 void p( int, int, int ); §\C{// equivalent prototypes}§ 2326 2326 void p( int x, int y, int z ); 2327 2327 void p( int y, int x, int z ); 2328 2328 void p( int z, int y, int x ); 2329 void p( int q, int r, int s ) {} 2329 void p( int q, int r, int s ) {} §\C{// match with this definition}§ 2330 2330 \end{cfa} 2331 2331 Forcing matching parameter names in routine prototypes with corresponding routine definitions is possible, but goes against a strong tradition in C programming. … … 2339 2339 int f( int x, double y ); 2340 2340 2341 f( j : 3, i : 4 ); 2342 f( x : 7, y : 8.1 ); 2343 f( 4, 5 ); 2341 f( j : 3, i : 4 ); §\C{// 1st f}§ 2342 f( x : 7, y : 8.1 ); §\C{// 2nd f}§ 2343 f( 4, 5 ); §\C{// ambiguous call}§ 2344 2344 \end{cfa} 2345 2345 However, named arguments compound routine resolution in conjunction with conversions: 2346 2346 \begin{cfa} 2347 f( i : 3, 5.7 ); 2347 f( i : 3, 5.7 ); §\C{// ambiguous call ?}§ 2348 2348 \end{cfa} 2349 2349 Depending on the cost associated with named arguments, this call could be resolvable or ambiguous. … … 2359 2359 the allowable positional calls are: 2360 2360 \begin{cfa} 2361 p(); 2362 p( 4 ); 2363 p( 4, 4 ); 2364 p( 4, 4, 4 ); 2361 p(); §\C{// rewrite $\Rightarrow$ p( 1, 2, 3 )}§ 2362 p( 4 ); §\C{// rewrite $\Rightarrow$ p( 4, 2, 3 )}§ 2363 p( 4, 4 ); §\C{// rewrite $\Rightarrow$ p( 4, 4, 3 )}§ 2364 p( 4, 4, 4 ); §\C{// rewrite $\Rightarrow$ p( 4, 4, 4 )}§ 2365 2365 // empty arguments 2366 p( , 4, 4 ); 2367 p( 4, , 4 ); 2368 p( 4, 4, ); 2369 p( 4, , ); 2370 p( , 4, ); 2371 p( , , 4 ); 2372 p( , , ); 2366 p( , 4, 4 ); §\C{// rewrite $\Rightarrow$ p( 1, 4, 4 )}§ 2367 p( 4, , 4 ); §\C{// rewrite $\Rightarrow$ p( 4, 2, 4 )}§ 2368 p( 4, 4, ); §\C{// rewrite $\Rightarrow$ p( 4, 4, 3 )}§ 2369 p( 4, , ); §\C{// rewrite $\Rightarrow$ p( 4, 2, 3 )}§ 2370 p( , 4, ); §\C{// rewrite $\Rightarrow$ p( 1, 4, 3 )}§ 2371 p( , , 4 ); §\C{// rewrite $\Rightarrow$ p( 1, 2, 4 )}§ 2372 p( , , ); §\C{// rewrite $\Rightarrow$ p( 1, 2, 3 )}§ 2373 2373 \end{cfa} 2374 2374 Here the missing arguments are inserted from the default values in the parameter list. … … 2394 2394 Default values may only appear in a prototype versus definition context: 2395 2395 \begin{cfa} 2396 void p( int x, int y = 2, int z = 3 ); 2397 void p( int, int = 2, int = 3 ); 2398 void p( int x, int y = 2, int z = 3 ) {} 2396 void p( int x, int y = 2, int z = 3 ); §\C{// prototype: allowed}§ 2397 void p( int, int = 2, int = 3 ); §\C{// prototype: allowed}§ 2398 void p( int x, int y = 2, int z = 3 ) {} §\C{// definition: not allowed}§ 2399 2399 \end{cfa} 2400 2400 The reason for this restriction is to allow separate compilation. … … 2421 2421 \begin{cfa} 2422 2422 void p( int x, int y = 2, int z = 3... ); 2423 p( 1, 4, 5, 6, z : 3 ); 2424 p( 1, z : 3, 4, 5, 6 ); 2423 p( 1, 4, 5, 6, z : 3 ); §\C{// assume p( /* positional */, ... , /* named */ );}§ 2424 p( 1, z : 3, 4, 5, 6 ); §\C{// assume p( /* positional */, /* named */, ... );}§ 2425 2425 \end{cfa} 2426 2426 The first call is an error because arguments 4 and 5 are actually positional not ellipse arguments; … … 2452 2452 Furthermore, overloading cannot handle accessing default arguments in the middle of a positional list, via a missing argument, such as: 2453 2453 \begin{cfa} 2454 p( 1, /* default */, 5 ); 2454 p( 1, /* default */, 5 ); §\C{// rewrite $\Rightarrow$ p( 1, 2, 5 )}§ 2455 2455 \end{cfa} 2456 2456 … … 2465 2465 \begin{cfa} 2466 2466 struct { 2467 int f1; 2468 int f2 : 4; 2469 int : 3; 2470 int ; 2471 int *; 2472 int (*)( int ); 2467 int f1; §\C{// named field}§ 2468 int f2 : 4; §\C{// named field with bit field size}§ 2469 int : 3; §\C{// unnamed field for basic type with bit field size}§ 2470 int ; §\C{// disallowed, unnamed field}§ 2471 int *; §\C{// disallowed, unnamed field}§ 2472 int (*)( int ); §\C{// disallowed, unnamed field}§ 2473 2473 }; 2474 2474 \end{cfa} … … 2478 2478 \begin{cfa} 2479 2479 struct { 2480 int , , ; 2480 int , , ; §\C{// 3 unnamed fields}§ 2481 2481 } 2482 2482 \end{cfa} … … 2572 2572 const unsigned int size = 5; 2573 2573 int ia[size]; 2574 ... 2575 qsort( ia, size ); 2574 ... §\C{// assign values to array ia}§ 2575 qsort( ia, size ); §\C{// sort ascending order using builtin ?<?}§ 2576 2576 { 2577 2577 ®int ?<?( int x, int y ) { return x > y; }® §\C{// nested routine}§ 2578 qsort( ia, size ); 2578 qsort( ia, size ); §\C{// sort descending order by local redefinition}§ 2579 2579 } 2580 2580 \end{cfa} … … 2584 2584 The following program in undefined in \CFA (and Indexc{gcc}) 2585 2585 \begin{cfa} 2586 [* [int]( int )] foo() { 2586 [* [int]( int )] foo() { §\C{// int (* foo())( int )}§ 2587 2587 int ®i® = 7; 2588 2588 int bar( int p ) { 2589 ®i® += 1; 2589 ®i® += 1; §\C{// dependent on local variable}§ 2590 2590 sout | ®i®; 2591 2591 } 2592 return bar; 2592 return bar; §\C{// undefined because of local dependence}§ 2593 2593 } 2594 2594 int main() { 2595 * [int]( int ) fp = foo(); 2595 * [int]( int ) fp = foo(); §\C{// int (* fp)( int )}§ 2596 2596 sout | fp( 3 ); 2597 2597 } … … 2606 2606 In C and \CFA, lists of elements appear in several contexts, such as the parameter list of a routine call. 2607 2607 \begin{cfa} 2608 f( ®2, x, 3 + i® ); 2608 f( ®2, x, 3 + i® ); §\C{// element list}§ 2609 2609 \end{cfa} 2610 2610 A list of elements is called a \newterm{tuple}, and is different from a \Index{comma expression}. … … 2623 2623 typedef struct { int quot, rem; } div_t; §\C[7cm]{// from include stdlib.h}§ 2624 2624 div_t div( int num, int den ); 2625 div_t qr = div( 13, 5 ); 2626 printf( "%d %d\n", qr.quot, qr.rem ); 2625 div_t qr = div( 13, 5 ); §\C{// return quotient/remainder aggregate}§ 2626 printf( "%d %d\n", qr.quot, qr.rem ); §\C{// print quotient/remainder}§ 2627 2627 \end{cfa} 2628 2628 This approach requires a name for the return type and fields, where \Index{naming} is a common programming-language issue. … … 2634 2634 For example, consider C's \Indexc{modf} function, which returns the integral and fractional part of a floating value. 2635 2635 \begin{cfa} 2636 double modf( double x, double * i ); 2637 double intp, frac = modf( 13.5, &intp ); 2638 printf( "%g %g\n", intp, frac ); 2636 double modf( double x, double * i ); §\C{// from include math.h}§ 2637 double intp, frac = modf( 13.5, &intp ); §\C{// return integral and fractional components}§ 2638 printf( "%g %g\n", intp, frac ); §\C{// print integral/fractional components}§ 2639 2639 \end{cfa} 2640 2640 This approach requires allocating storage for the return values, which complicates the call site with a sequence of variable declarations leading to the call. … … 2663 2663 When a function call is passed as an argument to another call, the best match of actual arguments to formal parameters is evaluated given all possible expression interpretations in the current scope. 2664 2664 \begin{cfa} 2665 void g( int, int ); 2666 void g( double, double ); 2667 g( div( 13, 5 ) ); 2668 g( modf( 13.5 ) ); 2665 void g( int, int ); §\C{// 1}§ 2666 void g( double, double ); §\C{// 2}§ 2667 g( div( 13, 5 ) ); §\C{// select 1}§ 2668 g( modf( 13.5 ) ); §\C{// select 2}§ 2669 2669 \end{cfa} 2670 2670 In this case, there are two overloaded ©g© routines. … … 2675 2675 The previous examples can be rewritten passing the multiple returned-values directly to the ©printf© function call. 2676 2676 \begin{cfa} 2677 [ int, int ] div( int x, int y ); 2678 printf( "%d %d\n", div( 13, 5 ) ); 2679 2680 [ double, double ] modf( double x ); 2681 printf( "%g %g\n", modf( 13.5 ) ); 2677 [ int, int ] div( int x, int y ); §\C{// from include stdlib}§ 2678 printf( "%d %d\n", div( 13, 5 ) ); §\C{// print quotient/remainder}§ 2679 2680 [ double, double ] modf( double x ); §\C{// from include math}§ 2681 printf( "%g %g\n", modf( 13.5 ) ); §\C{// print integral/fractional components}§ 2682 2682 \end{cfa} 2683 2683 This approach provides the benefits of compile-time checking for appropriate return statements as in aggregation, but without the required verbosity of declaring a new named type. … … 2689 2689 \begin{cfa} 2690 2690 int quot, rem; 2691 [ quot, rem ] = div( 13, 5 ); 2692 printf( "%d %d\n", quot, rem ); 2691 [ quot, rem ] = div( 13, 5 ); §\C{// assign multiple variables}§ 2692 printf( "%d %d\n", quot, rem ); §\C{// print quotient/remainder}\CRT§ 2693 2693 \end{cfa} 2694 2694 Here, the multiple return-values are matched in much the same way as passing multiple return-values to multiple parameters in a call. … … 2716 2716 In \CFA, it is possible to overcome this restriction by declaring a \newterm{tuple variable}. 2717 2717 \begin{cfa} 2718 [int, int] ®qr® = div( 13, 5 ); 2719 printf( "%d %d\n", ®qr® ); 2718 [int, int] ®qr® = div( 13, 5 ); §\C{// initialize tuple variable}§ 2719 printf( "%d %d\n", ®qr® ); §\C{// print quotient/remainder}§ 2720 2720 \end{cfa} 2721 2721 It is now possible to match the multiple return-values to a single variable, in much the same way as \Index{aggregation}. … … 2723 2723 One way to access the individual components of a tuple variable is with assignment. 2724 2724 \begin{cfa} 2725 [ quot, rem ] = qr; 2725 [ quot, rem ] = qr; §\C{// assign multiple variables}§ 2726 2726 \end{cfa} 2727 2727 … … 2746 2746 [int, double] * p; 2747 2747 2748 int y = x.0; 2749 y = f().1; 2750 p->0 = 5; 2751 g( x.1, x.0 ); 2752 double z = [ x, f() ].0.1; 2748 int y = x.0; §\C{// access int component of x}§ 2749 y = f().1; §\C{// access int component of f}§ 2750 p->0 = 5; §\C{// access int component of tuple pointed-to by p}§ 2751 g( x.1, x.0 ); §\C{// rearrange x to pass to g}§ 2752 double z = [ x, f() ].0.1; §\C{// access second component of first component of tuple expression}§ 2753 2753 \end{cfa} 2754 2754 Tuple-index expressions can occur on any tuple-typed expression, including tuple-returning functions, square-bracketed tuple expressions, and other tuple-index expressions, provided the retrieved component is also a tuple. … … 2817 2817 double y; 2818 2818 [int, double] z; 2819 [y, x] = 3.14; 2819 [y, x] = 3.14; §\C{// mass assignment}§ 2820 2820 [x, y] = z; §\C{// multiple assignment}§ 2821 2821 z = 10; §\C{// mass assignment}§ 2822 z = [x, y]; 2822 z = [x, y]; §\C{// multiple assignment}§ 2823 2823 \end{cfa} 2824 2824 Let $L_i$ for $i$ in $[0, n)$ represent each component of the flattened left side, $R_i$ represent each component of the flattened right side of a multiple assignment, and $R$ represent the right side of a mass assignment. … … 2864 2864 double c, d; 2865 2865 [ void ] f( [ int, int ] ); 2866 f( [ c, a ] = [ b, d ] = 1.5 ); // assignments in parameter list2866 f( [ c, a ] = [ b, d ] = 1.5 ); §\C{// assignments in parameter list}§ 2867 2867 \end{cfa} 2868 2868 The tuple expression begins with a mass assignment of ©1.5© into ©[b, d]©, which assigns ©1.5© into ©b©, which is truncated to ©1©, and ©1.5© into ©d©, producing the tuple ©[1, 1.5]© as a result. … … 2877 2877 \begin{cfa} 2878 2878 struct S; 2879 void ?{}(S *); // (1)2880 void ?{}(S *, int); // (2)2881 void ?{}(S * double); // (3)2882 void ?{}(S *, S); // (4)2883 2884 [S, S] x = [3, 6.28]; // uses (2), (3), specialized constructors2885 [S, S] y; // uses (1), (1), default constructor2886 [S, S] z = x.0; // uses (4), (4), copy constructor2879 void ?{}(S *); §\C{// (1)}§ 2880 void ?{}(S *, int); §\C{// (2)}§ 2881 void ?{}(S * double); §\C{// (3)}§ 2882 void ?{}(S *, S); §\C{// (4)}§ 2883 2884 [S, S] x = [3, 6.28]; §\C{// uses (2), (3), specialized constructors}§ 2885 [S, S] y; §\C{// uses (1), (1), default constructor}§ 2886 [S, S] z = x.0; §\C{// uses (4), (4), copy constructor}§ 2887 2887 \end{cfa} 2888 2888 In this example, ©x© is initialized by the multiple constructor calls ©?{}(&x.0, 3)© and ©?{}(&x.1, 6.28)©, while ©y© is initialized by two default constructor calls ©?{}(&y.0)© and ©?{}(&y.1)©. … … 2925 2925 A member-access tuple may be used anywhere a tuple can be used, \eg: 2926 2926 \begin{cfa} 2927 s.[ y, z, x ] = [ 3, 3.2, 'x' ]; 2928 f( s.[ y, z ] ); 2927 s.[ y, z, x ] = [ 3, 3.2, 'x' ]; §\C{// equivalent to s.x = 'x', s.y = 3, s.z = 3.2}§ 2928 f( s.[ y, z ] ); §\C{// equivalent to f( s.y, s.z )}§ 2929 2929 \end{cfa} 2930 2930 Note, the fields appearing in a record-field tuple may be specified in any order; … … 2936 2936 void f( double, long ); 2937 2937 2938 f( x.[ 0, 3 ] ); 2939 x.[ 0, 1 ] = x.[ 1, 0 ]; 2938 f( x.[ 0, 3 ] ); §\C{// f( x.0, x.3 )}§ 2939 x.[ 0, 1 ] = x.[ 1, 0 ]; §\C{// [ x.0, x.1 ] = [ x.1, x.0 ]}§ 2940 2940 [ long, int, long ] y = x.[ 2, 0, 2 ]; 2941 2941 \end{cfa} … … 2954 2954 \begin{cfa} 2955 2955 [ int, float, double ] f(); 2956 [ double, float ] x = f().[ 2, 1 ]; 2956 [ double, float ] x = f().[ 2, 1 ]; §\C{// f() called once}§ 2957 2957 \end{cfa} 2958 2958 … … 2967 2967 That is, a cast can be used to select the type of an expression when it is ambiguous, as in the call to an overloaded function. 2968 2968 \begin{cfa} 2969 int f(); // (1)2970 double f(); // (2)2971 2972 f(); // ambiguous - (1),(2) both equally viable2973 (int)f(); // choose (2)2969 int f(); §\C{// (1)}§ 2970 double f(); §\C{// (2)}§ 2971 2972 f(); §\C{// ambiguous - (1),(2) both equally viable}§ 2973 (int)f(); §\C{// choose (2)}§ 2974 2974 \end{cfa} 2975 2975 Since casting is a fundamental operation in \CFA, casts need to be given a meaningful interpretation in the context of tuples. … … 2979 2979 void g(); 2980 2980 2981 (void)f(); // valid, ignore results2982 (int)g(); // invalid, void cannot be converted to int2981 (void)f(); §\C{// valid, ignore results}§ 2982 (int)g(); §\C{// invalid, void cannot be converted to int}§ 2983 2983 2984 2984 struct A { int x; }; 2985 (struct A)f(); // invalid, int cannot be converted to A2985 (struct A)f(); §\C{// invalid, int cannot be converted to A}§ 2986 2986 \end{cfa} 2987 2987 In C, line 4 is a valid cast, which calls ©f© and discards its result. … … 2999 2999 [int, [int, int], int] g(); 3000 3000 3001 ([int, double])f(); // (1) valid3002 ([int, int, int])g(); // (2) valid3003 ([void, [int, int]])g(); // (3) valid3004 ([int, int, int, int])g(); // (4) invalid3005 ([int, [int, int, int]])g(); // (5) invalid3001 ([int, double])f(); §\C{// (1) valid}§ 3002 ([int, int, int])g(); §\C{// (2) valid}§ 3003 ([void, [int, int]])g(); §\C{// (3) valid}§ 3004 ([int, int, int, int])g(); §\C{// (4) invalid}§ 3005 ([int, [int, int, int]])g(); §\C{// (5) invalid}§ 3006 3006 \end{cfa} 3007 3007 … … 3063 3063 void f([int, int], int, int); 3064 3064 3065 f([0, 0], 0, 0); // no cost3066 f(0, 0, 0, 0); // cost for structuring3067 f([0, 0,], [0, 0]); // cost for flattening3068 f([0, 0, 0], 0); // cost for flattening and structuring3065 f([0, 0], 0, 0); §\C{// no cost}§ 3066 f(0, 0, 0, 0); §\C{// cost for structuring}§ 3067 f([0, 0,], [0, 0]); §\C{// cost for flattening}§ 3068 f([0, 0, 0], 0); §\C{// cost for flattening and structuring}§ 3069 3069 \end{cfa} 3070 3070 … … 3129 3129 [ unsigned int, char ] 3130 3130 [ double, double, double ] 3131 [ * int, int * ] 3131 [ * int, int * ] §\C{// mix of CFA and ANSI}§ 3132 3132 [ * [ 5 ] int, * * char, * [ [ int, int ] ] (int, int) ] 3133 3133 \end{cfa} … … 3136 3136 Examples of declarations using tuple types are: 3137 3137 \begin{cfa} 3138 [ int, int ] x; 3139 * [ char, char ] y; 3138 [ int, int ] x; §\C{// 2 element tuple, each element of type int}§ 3139 * [ char, char ] y; §\C{// pointer to a 2 element tuple}§ 3140 3140 [ [ int, int ] ] z ([ int, int ]); 3141 3141 \end{cfa} … … 3154 3154 [ int, int ] w1; 3155 3155 [ int, int, int ] w2; 3156 [ void ] f (int, int, int); /* three input parameters of type int */3157 [ void ] g ([ int, int, int ]); /* 3 element tuple as input */3156 [ void ] f (int, int, int); §\C{// three input parameters of type int}§ 3157 [ void ] g ([ int, int, int ]); §\C{3 element tuple as input}§ 3158 3158 f( [ 1, 2, 3 ] ); 3159 3159 f( w1, 3 ); … … 3235 3235 [ int, int, int, int ] w = [ 1, 2, 3, 4 ]; 3236 3236 int x = 5; 3237 [ x, w ] = [ w, x ]; 3237 [ x, w ] = [ w, x ]; §\C{// all four tuple coercions}§ 3238 3238 \end{cfa} 3239 3239 Starting on the right-hand tuple in the last assignment statement, w is opened, producing a tuple of four values; … … 3323 3323 both these examples produce indeterminate results: 3324 3324 \begin{cfa} 3325 f( x++, x++ ); 3326 [ v1, v2 ] = [ x++, x++ ]; 3325 f( x++, x++ ); §\C{// C routine call with side effects in arguments}§ 3326 [ v1, v2 ] = [ x++, x++ ]; §\C{// side effects in righthand side of multiple assignment}§ 3327 3327 \end{cfa} 3328 3328 … … 3346 3346 3347 3347 3348 \section{I/O Library} 3349 \label{s:IOLibrary} 3350 \index{input/output library} 3351 3352 The goal of \CFA I/O is to simplify the common cases\index{I/O!common case}, while fully supporting polymorphism and user defined types in a consistent way. 3353 The approach combines ideas from \CC and Python. 3354 The \CFA header file for the I/O library is \Indexc{fstream}. 3355 3356 The common case is printing out a sequence of variables separated by whitespace. 3348 \section{I/O Stream Library} 3349 \label{s:IOStreamLibrary} 3350 \index{input/output stream library} 3351 \index{stream library} 3352 3353 The goal of \CFA input/output (I/O) is to simplify the common cases\index{I/O!common case}, while fully supporting polymorphism and user defined types in a consistent way. 3354 \CFA I/O combines ideas from C ©printf©, \CC, and Python. 3355 I/O can be unformatted or formatted. 3356 Unformatted means \CFA selects the output or input format for values that match with the type of a variable. 3357 Formatted means additional information is specified to augment how an output or input of value is interpreted. 3358 \CFA formatting is a cross between C ©printf© and \CC ©cout© manipulators. 3359 \begin{itemize} 3360 \item 3361 ©printf© format codes are dense, making them difficult to read and remember. 3362 \CFA/\CC format manipulators are named, making them easier to read and remember. 3363 \item 3364 ©printf© separates format codes from associated variables, making it difficult to match codes with variables. 3365 \CFA/\CC co-locate codes with associated variables, where \CFA has the tighter binding. 3366 \item 3367 Format manipulators in \CC have global rather than local effect, except ©setw©. 3368 Hence, it is common programming practice to toggle manipulators on and then back to the default to prevent downstream side-effects. 3369 Without this programming style, errors occur when moving prints, as manipulator effects incorrectly flow into the new location. 3370 (To guarantee no side-effects, manipulator values must be saved and restored across function calls.) 3371 \end{itemize} 3372 The \CFA header file for the I/O library is \Indexc{fstream.hfa}. 3373 3374 For unformatted output, the common case is printing a sequence of variables separated by whitespace. 3357 3375 \begin{cquote} 3358 3376 \begin{tabular}{@{}l@{\hspace{3em}}l@{}} … … 3373 3391 & 3374 3392 \begin{cfa}[showspaces=true,aboveskip=0pt,belowskip=0pt] 3375 1 233393 1® ®2® ®3 3376 3394 \end{cfa} 3377 3395 \end{tabular} 3378 3396 \end{cquote} 3379 The \CFA form has half the characters of the \CC form, and is similar to \Index*{Python} I/O with respect to implicit separators .3380 Similar simplification occurs for \Index{tuple} I/O, which prints all tuple valuesseparated by ``\lstinline[showspaces=true]@, @''.3397 The \CFA form has half the characters of the \CC form, and is similar to \Index*{Python} I/O with respect to implicit separators and newline. 3398 Similar simplification occurs for \Index{tuple} I/O, which flattens the tuple and prints each value separated by ``\lstinline[showspaces=true]@, @''. 3381 3399 \begin{cfa} 3382 3400 [int, [ int, int ] ] t1 = [ 1, [ 2, 3 ] ], t2 = [ 4, [ 5, 6 ] ]; 3383 sout | t1 | t2; 3401 sout | t1 | t2; §\C{// print tuples}§ 3384 3402 \end{cfa} 3385 3403 \begin{cfa}[showspaces=true,aboveskip=0pt] 3386 3404 1®, ®2®, ®3 4®, ®5®, ®6 3387 3405 \end{cfa} 3388 Finally, \CFA uses the logical-or operator for I/O as it is the lowest-priority overloadableoperator, other than assignment.3406 Finally, \CFA uses the logical-or operator for I/O as it is the lowest-priority \emph{overloadable} operator, other than assignment. 3389 3407 Therefore, fewer output expressions require parenthesis. 3390 3408 \begin{cquote} … … 3393 3411 & 3394 3412 \begin{cfa} 3395 sout | x * 3 | y + 1 | z << 2 | x == y | (x | y) | (x || y) | (x > z ? 1 : 2);3413 sout | x * 3 | y + 1 | z << 2 | x == y | ®(®x | y®)® | ®(®x || y®)® | ®(®x > z ? 1 : 2®)®; 3396 3414 \end{cfa} 3397 3415 \\ … … 3399 3417 & 3400 3418 \begin{cfa} 3401 cout << x * 3 << y + 1 << ®(®z << 2®)® << ®(®x == y®)® << (x | y) << (x || y) << (x > z ? 1 : 2)<< endl;3419 cout << x * 3 << y + 1 << ®(®z << 2®)® << ®(®x == y®)® << ®(®x | y®)® << ®(®x || y®)® << ®(®x > z ? 1 : 2®)® << endl; 3402 3420 \end{cfa} 3403 3421 \\ … … 3408 3426 \end{tabular} 3409 3427 \end{cquote} 3410 There is a weak similarity between the \CFA logical-or operator and the Shell pipe-operator for moving data, where data flows in the correct direction for input but the opposite direction for output. 3428 Input and output use a uniform operator, ©|©, rather than separate operators, as in ©>>© and ©<<© for \CC. 3429 There is a weak similarity between the \CFA logical-or operator and the \Index{Shell pipe-operator} for moving data, where data flows in the correct direction for input but the opposite direction for output. 3430 3431 For unformatter input, the common case is reading a sequence of values separated by whitespace, where the type of an input constant must match with the type of the input variable. 3432 \begin{cquote} 3433 \begin{lrbox}{\LstBox} 3434 \begin{cfa}[aboveskip=0pt,belowskip=0pt] 3435 int x; double y char z; 3436 \end{cfa} 3437 \end{lrbox} 3438 \begin{tabular}{@{}l@{\hspace{3em}}l@{}} 3439 \multicolumn{1}{@{}l@{}}{\usebox\LstBox} \\ 3440 \multicolumn{1}{c@{\hspace{3em}}}{\textbf{\CFA}} & \multicolumn{1}{c}{\textbf{\CC}} \\ 3441 \begin{cfa}[aboveskip=0pt,belowskip=0pt] 3442 sin | x | y | z; 3443 \end{cfa} 3444 & 3445 \begin{cfa}[aboveskip=0pt,belowskip=0pt] 3446 cin >> x >> y >> z; 3447 \end{cfa} 3448 \\ 3449 \begin{cfa}[showspaces=true,aboveskip=0pt,belowskip=0pt] 3450 ®1® ®2.5® ®A® 3451 \end{cfa} 3452 & 3453 \begin{cfa}[showspaces=true,aboveskip=0pt,belowskip=0pt] 3454 ®1® ®2.5® ®A® 3455 \end{cfa} 3456 \end{tabular} 3457 \end{cquote} 3458 3411 3459 3412 3460 3413 3461 \subsection{Implicit Separator} 3414 3462 3415 The \Index{implicit separator}\index{I/O!separator} character (space/blank) is a separator not a terminator .3463 The \Index{implicit separator}\index{I/O!separator} character (space/blank) is a separator not a terminator for output. 3416 3464 The rules for implicitly adding the separator are: 3417 3465 \begin{enumerate} … … 3441 3489 3442 3490 \item 3443 A separator does not appear before a C string starting with the (extended) \Index*{ASCII}\index{ASCII!extended} characters: \lstinline[mathescape=off,basicstyle=\tt]@([{=$£¥¡¿«@ 3491 {\lstset{language=CFA,deletedelim=**[is][]{¢}{¢}} 3492 A seperator does not appear before a C string starting with the (extended) \Index*{ASCII}\index{ASCII!extended} characters: \lstinline[basicstyle=\tt]@,.;!?)]}%¢»@ 3493 \begin{cfa}[belowskip=0pt] 3494 sout | 1 | ", x" | 2 | ". x" | 3 | "; x" | 4 | "! x" | 5 | "? x" | 6 | "% x" 3495 | 7 | "¢ x" | 8 | "» x" | 9 | ") x" | 10 | "] x" | 11 | "} x"; 3496 \end{cfa} 3497 \begin{cfa}[basicstyle=\tt,showspaces=true,aboveskip=0pt,belowskip=0pt] 3498 1®,® x 2®.® x 3®;® x 4®!® x 5®?® x 6®%® x 7§\color{red}\textcent§ x 8®»® x 9®)® x 10®]® x 11®}® x 3499 \end{cfa}}% 3500 where \lstinline[basicstyle=\tt]@»@ is a closing citation mark. 3501 3502 \item 3503 A separator does not appear after a C string ending with the (extended) \Index*{ASCII}\index{ASCII!extended} characters: \lstinline[mathescape=off,basicstyle=\tt]@([{=$£¥¡¿«@ 3444 3504 %$ 3445 3505 \begin{cfa}[mathescape=off] … … 3455 3515 3456 3516 \item 3457 {\lstset{language=CFA,deletedelim=**[is][]{¢}{¢}} 3458 A seperator does not appear after a C string ending with the (extended) \Index*{ASCII}\index{ASCII!extended} characters: \lstinline[basicstyle=\tt]@,.;!?)]}%¢»@ 3459 \begin{cfa}[belowskip=0pt] 3460 sout | 1 | ", x" | 2 | ". x" | 3 | "; x" | 4 | "! x" | 5 | "? x" | 6 | "% x" 3461 | 7 | "¢ x" | 8 | "» x" | 9 | ") x" | 10 | "] x" | 11 | "} x"; 3462 \end{cfa} 3463 \begin{cfa}[basicstyle=\tt,showspaces=true,aboveskip=0pt,belowskip=0pt] 3464 1®,® x 2®.® x 3®;® x 4®!® x 5®?® x 6®%® x 7§\color{red}\textcent§ x 8®»® x 9®)® x 10®]® x 11®}® x 3465 \end{cfa}}% 3466 where \lstinline[basicstyle=\tt]@»@ is a closing citation mark. 3467 3468 \item 3469 A seperator does not appear before or after a C string begining/ending with the \Index*{ASCII} quote or whitespace characters: \lstinline[basicstyle=\tt,showspaces=true]@`'": \t\v\f\r\n@ 3517 A seperator does not appear before/after a C string starting/ending with the \Index*{ASCII} quote or whitespace characters: \lstinline[basicstyle=\tt,showspaces=true]@`'": \t\v\f\r\n@ 3470 3518 \begin{cfa}[belowskip=0pt] 3471 3519 sout | "x`" | 1 | "`x'" | 2 | "'x\"" | 3 | "\"x:" | 4 | ":x " | 5 | " x\t" | 6 | "\tx"; … … 3486 3534 3487 3535 3488 \subsection{Manipulator} 3489 3490 The following \CC-style \Index{manipulator}s and routines control implicit seperation. 3536 \subsection{Separation Manipulators} 3537 3538 The following \Index{manipulator}s control \Index{implicit output separation}. 3539 The effect of these manipulators is global for an output stream (except ©sepOn© and ©sepOff©). 3491 3540 \begin{enumerate} 3492 3541 \item 3493 Routines\Indexc{sepSet}\index{manipulator!sepSet@©sepSet©} and \Indexc{sep}\index{manipulator!sep@©sep©}/\Indexc{sepGet}\index{manipulator!sepGet@©sepGet©} set and get the separator string.3542 \Indexc{sepSet}\index{manipulator!sepSet@©sepSet©} and \Indexc{sep}\index{manipulator!sep@©sep©}/\Indexc{sepGet}\index{manipulator!sepGet@©sepGet©} set and get the separator string. 3494 3543 The separator string can be at most 16 characters including the ©'\0'© string terminator (15 printable characters). 3495 3544 \begin{cfa}[mathescape=off,belowskip=0pt] 3496 sepSet( sout, ", $" ); 3545 sepSet( sout, ", $" ); §\C{// set separator from " " to ", \$"}§ 3497 3546 sout | 1 | 2 | 3 | " \"" | ®sep® | "\""; 3498 3547 \end{cfa} … … 3503 3552 %$ 3504 3553 \begin{cfa}[belowskip=0pt] 3505 sepSet( sout, " " ); 3554 sepSet( sout, " " ); §\C{// reset separator to " "}§ 3506 3555 sout | 1 | 2 | 3 | " \"" | ®sepGet( sout )® | "\""; 3507 3556 \end{cfa} … … 3511 3560 ©sepGet© can be used to store a separator and then restore it: 3512 3561 \begin{cfa}[belowskip=0pt] 3513 char store[®sepSize®]; 3514 strcpy( store, sepGet( sout ) ); 3515 sepSet( sout, "_" ); 3562 char store[®sepSize®]; §\C{// sepSize is the maximum separator size}§ 3563 strcpy( store, sepGet( sout ) ); §\C{// copy current separator}§ 3564 sepSet( sout, "_" ); §\C{// change separator to underscore}§ 3516 3565 sout | 1 | 2 | 3; 3517 3566 \end{cfa} … … 3520 3569 \end{cfa} 3521 3570 \begin{cfa}[belowskip=0pt] 3522 sepSet( sout, store ); 3571 sepSet( sout, store ); §\C{// change separator back to original}§ 3523 3572 sout | 1 | 2 | 3; 3524 3573 \end{cfa} … … 3528 3577 3529 3578 \item 3530 Routine\Indexc{sepSetTuple}\index{manipulator!sepSetTuple@©sepSetTuple©} and \Indexc{sepTuple}\index{manipulator!sepTuple@©sepTuple©}/\Indexc{sepGetTuple}\index{manipulator!sepGetTuple@©sepGetTuple©} get and set the tuple separator-string.3579 \Indexc{sepSetTuple}\index{manipulator!sepSetTuple@©sepSetTuple©} and \Indexc{sepTuple}\index{manipulator!sepTuple@©sepTuple©}/\Indexc{sepGetTuple}\index{manipulator!sepGetTuple@©sepGetTuple©} get and set the tuple separator-string. 3531 3580 The tuple separator-string can be at most 16 characters including the ©'\0'© string terminator (15 printable characters). 3532 3581 \begin{cfa}[belowskip=0pt] 3533 sepSetTuple( sout, " " ); 3582 sepSetTuple( sout, " " ); §\C{// set tuple separator from ", " to " "}§ 3534 3583 sout | t1 | t2 | " \"" | ®sepTuple® | "\""; 3535 3584 \end{cfa} … … 3538 3587 \end{cfa} 3539 3588 \begin{cfa}[belowskip=0pt] 3540 sepSetTuple( sout, ", " ); 3589 sepSetTuple( sout, ", " ); §\C{// reset tuple separator to ", "}§ 3541 3590 sout | t1 | t2 | " \"" | ®sepGetTuple( sout )® | "\""; 3542 3591 \end{cfa} … … 3547 3596 3548 3597 \item 3549 Manipulators \Indexc{sepDisable}\index{manipulator!sepDisable@©sepDisable©} and \Indexc{sepEnable}\index{manipulator!sepEnable@©sepEnable©} \emph{globally} toggle printing the separator, \ie the seperator is adjusted with respect to all subsequent printed items.3598 \Indexc{sepDisable}\index{manipulator!sepDisable@©sepDisable©} and \Indexc{sepEnable}\index{manipulator!sepEnable@©sepEnable©} toggle printing the separator. 3550 3599 \begin{cfa}[belowskip=0pt] 3551 sout | sepDisable | 1 | 2 | 3; §\C{// globallyturn off implicit separator}§3600 sout | sepDisable | 1 | 2 | 3; §\C{// turn off implicit separator}§ 3552 3601 \end{cfa} 3553 3602 \begin{cfa}[showspaces=true,aboveskip=0pt,belowskip=0pt] … … 3555 3604 \end{cfa} 3556 3605 \begin{cfa}[belowskip=0pt] 3557 sout | sepEnable | 1 | 2 | 3; §\C{// globallyturn on implicit separator}§3606 sout | sepEnable | 1 | 2 | 3; §\C{// turn on implicit separator}§ 3558 3607 \end{cfa} 3559 3608 \begin{cfa}[mathescape=off,showspaces=true,aboveskip=0pt,belowskip=0pt] … … 3562 3611 3563 3612 \item 3564 Manipulators \Indexc{sepOn}\index{manipulator!sepOn@©sepOn©} and \Indexc{sepOff}\index{manipulator!sepOff@©sepOff©} \emph{locally} toggle printing the separator, \ie the seperator is adjusted only with respect to the next printed item.3613 \Indexc{sepOn}\index{manipulator!sepOn@©sepOn©} and \Indexc{sepOff}\index{manipulator!sepOff@©sepOff©} toggle printing the separator with respect to the next printed item, and then return to the global seperator setting. 3565 3614 \begin{cfa}[belowskip=0pt] 3566 sout | 1 | sepOff | 2 | 3; §\C{// locally turn off implicit separator}§3615 sout | 1 | sepOff | 2 | 3; §\C{// turn off implicit separator for the next item}§ 3567 3616 \end{cfa} 3568 3617 \begin{cfa}[showspaces=true,aboveskip=0pt,belowskip=0pt] … … 3570 3619 \end{cfa} 3571 3620 \begin{cfa}[belowskip=0pt] 3572 sout | sepDisable | 1 | sepOn | 2 | 3; §\C{// locally turn on implicit separator}§3621 sout | sepDisable | 1 | sepOn | 2 | 3; §\C{// turn on implicit separator for the next item}§ 3573 3622 \end{cfa} 3574 3623 \begin{cfa}[showspaces=true,aboveskip=0pt,belowskip=0pt] … … 3577 3626 The tuple separator also responses to being turned on and off. 3578 3627 \begin{cfa}[belowskip=0pt] 3579 sout | t1 | sepOff | t2; 3628 sout | t1 | sepOff | t2; §\C{// locally turn on/off implicit separator}§ 3580 3629 \end{cfa} 3581 3630 \begin{cfa}[showspaces=true,aboveskip=0pt,belowskip=0pt] … … 3585 3634 use ©sep© to accomplish this functionality. 3586 3635 \begin{cfa}[belowskip=0pt] 3587 sout | sepOn | 1 | 2 | 3 | sepOn; 3636 sout | sepOn | 1 | 2 | 3 | sepOn; §\C{// sepOn does nothing at start/end of line}§ 3588 3637 \end{cfa} 3589 3638 \begin{cfa}[showspaces=true,aboveskip=0pt,belowskip=0pt] … … 3591 3640 \end{cfa} 3592 3641 \begin{cfa}[belowskip=0pt] 3593 sout | sep | 1 | 2 | 3 | sep ; 3642 sout | sep | 1 | 2 | 3 | sep ; §\C{// use sep to print separator at start/end of line}§ 3594 3643 \end{cfa} 3595 3644 \begin{cfa}[showspaces=true,aboveskip=0pt,belowskip=0pt] 3596 3645 ® ®1 2 3® ® 3646 \end{cfa} 3647 \end{enumerate} 3648 3649 3650 \subsection{Newline Manipulators} 3651 3652 The following \Index{manipulator} controls \Index{newline separation} for input and output. 3653 3654 For input: 3655 \begin{enumerate}[parsep=0pt] 3656 \item 3657 \Indexc{nl}\index{manipulator!nl@©nl©} scans characters until the next newline character, i.e., ignore the remaining characters in the line. 3658 \item 3659 \Indexc{nlOn}\index{manipulator!nlOn@©nlOn©} reads the newline character, when reading single characters. 3660 \item 3661 \Indexc{nlOff}\index{manipulator!nlOff@©nlOff©} does \emph{not} read the newline character, when reading single characters. 3662 \end{enumerate} 3663 For example, in: 3664 \begin{cfa} 3665 sin | i | ®nl® | j; 3666 1 ®2® 3667 3 3668 \end{cfa} 3669 variable ©i© is assigned 1, the 2 is skipped, and variable ©j© is assigned 3. 3670 3671 For output: 3672 \begin{enumerate}[parsep=0pt] 3673 \item 3674 \Indexc{nl}\index{manipulator!nl@©nl©} inserts a newline. 3675 \begin{cfa} 3676 sout | nl; §\C{// only print newline}§ 3677 sout | 2; §\C{// implicit newline}§ 3678 sout | 3 | nl | 4 | nl; §\C{// terminating nl merged with implicit newline}§ 3679 sout | 5 | nl | nl; §\C{// again terminating nl merged with implicit newline}§ 3680 sout | 6; §\C{// implicit newline}§ 3681 3682 2 3683 3 3684 4 3685 5 3686 3687 6 3688 \end{cfa} 3689 Note, a terminating ©nl© is merged (overrides) with the implicit newline at the end of the ©sout© expression, otherwise it is impossible to to print a single newline 3690 \item 3691 \Indexc{nlOn}\index{manipulator!nlOn@©nlOn©} implicitly prints a newline at the end of each output expression. 3692 \item 3693 \Indexc{nlOff}\index{manipulator!nlOff@©nlOff©} does \emph{not} implicitly print a newline at the end of each output expression. 3694 \end{enumerate} 3695 3696 3697 \subsection{Output Value Manipulators} 3698 3699 The following \Index{manipulator}s control formatting of output values (printing), and only affect the format of the argument. 3700 \begin{enumerate} 3701 \item 3702 \Indexc{bin}( integer )\index{manipulator!bin@©bin©} print value in base 2 preceded by ©0b©/©0B©. 3703 \begin{cfa}[belowskip=0pt] 3704 sout | bin( 0 ) | bin( 27HH ) | bin( 27H ) | bin( 27 ) | bin( 27L ); 3705 0b0 0b11011 0b11011 0b11011 0b11011 3706 sout | bin( -27HH ) | bin( -27H ) | bin( -27 ) | bin( -27L ); 3707 0b11100101 0b1111111111100101 0b11111111111111111111111111100101 0b(58 1s)100101 3708 \end{cfa} 3709 3710 \item 3711 \Indexc{oct}( integer )\index{manipulator!oct@©oct©} print value in base 8 preceded by ©0©. 3712 \begin{cfa}[belowskip=0pt] 3713 sout | oct( 0 ) | oct( 27HH ) | oct( 27H ) | oct( 27 ) | oct( 27L ); 3714 0 033 033 033 033 3715 sout | oct( -27HH ) | oct( -27H ) | oct( -27 ) | oct( -27L ); 3716 0345 0177745 037777777745 01777777777777777777745 3717 \end{cfa} 3718 Note, octal 0 is \emph{not} preceded by ©0© to prevent confusion. 3719 3720 \item 3721 \Indexc{hex}( integer / floating-point )\index{manipulator!hex@©hex©} print value in base 16 preceded by ©0x©/©0X©. 3722 \begin{cfa}[belowskip=0pt] 3723 sout | hex( 0 ) | hex( 27HH ) | hex( 27H ) | hex( 27 ) | hex( 27L ); 3724 0 0x1b 0x1b 0x1b 0x1b 3725 sout | hex( -27HH ) | hex( -27H ) | hex( -27 ) | hex( -27L ); 3726 0xe5 0xffe5 0xffffffe5 0xffffffffffffffe5 3727 3728 sout | hex( 0.0 ) | hex( 27.5F ) | hex( 27.5 ) | hex( 27.5L ); 3729 0x0.p+0 0x1.b8p+4 0x1.b8p+4 0xd.cp+1 3730 sout | hex( -27.5F ) | hex( -27.5 ) | hex( -27.5L ); 3731 -0x1.b8p+4 -0x1.b8p+4 -0xd.cp+1 3732 \end{cfa} 3733 3734 \item 3735 \Indexc{sci}( floating-point )\index{manipulator!sci@©sci©} print value in scientific notation with exponent. 3736 Default is 6 digits of precision. 3737 \begin{cfa}[belowskip=0pt] 3738 sout | sci( 0.0 ) | sci( 27.5 ) | sci( -27.5 ); 3739 0.000000e+00 2.750000e+01 -2.750000e+01 3740 \end{cfa} 3741 3742 \item 3743 \Indexc{upcase}( bin / hex / floating-point )\index{manipulator!upcase@©upcase©} print letters in a value in upper case. Lower case is the default. 3744 \begin{cfa}[belowskip=0pt] 3745 sout | upcase( bin( 27 ) ) | upcase( hex( 27 ) ) | upcase( 27.5e-10 ) | upcase( hex( 27.5 ) ); 3746 0®B®11011 0®X®1®B® 2.75®E®-09 0®X®1.®B®8®P®+4 3747 \end{cfa} 3748 3749 \item 3750 \Indexc{nobase}( integer )\index{manipulator!nobase@©nobase©} do not precede ©bin©, ©oct©, ©hex© with ©0b©/©0B©, ©0©, or ©0x©/©0X©. Printing the base is the default. 3751 \begin{cfa}[belowskip=0pt] 3752 sout | nobase( bin( 27 ) ) | nobase( oct( 27 ) ) | nobase( hex( 27 ) ); 3753 11011 33 1b 3754 \end{cfa} 3755 3756 \item 3757 \Indexc{nodp}( floating-point )\index{manipulator!nodp@©nodp©} do not print a decimal point if there are no fractional digits. 3758 Printing a decimal point is the default, if there are no fractional digits. 3759 \begin{cfa}[belowskip=0pt] 3760 sout | 0. | nodp( 0. ) | 27.0 | nodp( 27.0 ) | nodp( 27.5 ); 3761 0.0 ®0® 27.0 ®27® 27.5 3762 \end{cfa} 3763 3764 \item 3765 \Indexc{sign}( integer / floating-point )\index{manipulator!sign@©sign©} prefix with plus or minus sign (©+© or ©-©). Only printing the minus sign is the default. 3766 \begin{cfa}[belowskip=0pt] 3767 sout | sign( 27 ) | sign( -27 ) | sign( 27. ) | sign( -27. ) | sign( 27.5 ) | sign( -27.5 ); 3768 ®+®27 -27 ®+®27.0 -27.0 ®+®27.5 -27.5 3769 \end{cfa} 3770 3771 \item 3772 \Indexc{wd}©( unsigned char minimum, T val )©\index{manipulator!wd@©wd©}, ©wd( unsigned char minimum, unsigned char precision, T val )© 3773 For all types, ©minimum© is the minimum number of printed characters. 3774 If the value is shorter than the minimum, it is padded on the right with spaces. 3775 \begin{cfa}[belowskip=0pt] 3776 sout | wd( 4, 34) | wd( 3, 34 ) | wd( 2, 34 ); 3777 sout | wd( 10, 4.) | wd( 9, 4. ) | wd( 8, 4. ); 3778 sout | wd( 4, "ab" ) | wd( 3, "ab" ) | wd( 2, "ab" ); 3779 \end{cfa} 3780 \begin{cfa}[showspaces=true,aboveskip=0pt,belowskip=0pt] 3781 ® ®34 ® ®34 34 3782 ® ®4.000000 ® ®4.000000 4.000000 3783 ® ®ab ® ®ab ab 3784 ab ab ab 3785 \end{cfa} 3786 If the value is larger, it is printed without truncation, ignoring the ©minimum©. 3787 \begin{cfa}[belowskip=0pt] 3788 sout | wd( 4, 34567 ) | wd( 3, 34567 ) | wd( 2, 34567 ); 3789 sout | wd( 4, 3456. ) | wd( 3, 3456. ) | wd( 2, 3456. ); 3790 sout | wd( 4, "abcde" ) | wd( 3, "abcde" ) | wd( 2,"abcde" ); 3791 \end{cfa} 3792 \begin{cfa}[showspaces=true,aboveskip=0pt,belowskip=0pt] 3793 3456®7® 345®67® 34®567® 3794 3456®.® 345®6.® 34®56.® 3795 abcd®e® abc®de® ab®cde® 3796 \end{cfa} 3797 3798 For integer types, ©precision© is the minimum number of printed digits. 3799 If the value is shorter, it is padded on the left with leading zeros. 3800 \begin{cfa}[belowskip=0pt] 3801 sout | wd( 4,3, 34 ) | wd( 8,4, 34 ) | wd( 10,10, 34 ); 3802 \end{cfa} 3803 \begin{cfa}[showspaces=true,aboveskip=0pt,belowskip=0pt] 3804 ®0®34 ®00®34 ®00000000®34 3805 \end{cfa} 3806 If the value is larger, it is printed without truncation, ignoring the ©precision©. 3807 \begin{cfa}[belowskip=0pt] 3808 sout | wd( 4,1, 3456 ) | wd( 8,2, 3456 ) | wd( 10,3, 3456 ); 3809 \end{cfa} 3810 \begin{cfa}[showspaces=true,aboveskip=0pt,belowskip=0pt] 3811 3456 3456 3456 3812 \end{cfa} 3813 If ©precision© is 0, nothing is printed for zero. 3814 If ©precision© is greater than the minimum, it becomes the minimum. 3815 \begin{cfa}[belowskip=0pt] 3816 sout | wd( 4,0, 0 ) | wd( 3,10, 34 ); 3817 \end{cfa} 3818 \begin{cfa}[showspaces=true,aboveskip=0pt,belowskip=0pt] 3819 ® ® ®00000000®34 3820 \end{cfa} 3821 For floating-point types, ©precision© is the minimum number of digits after the decimal point. 3822 \begin{cfa}[belowskip=0pt] 3823 sout | wd( 6,3, 27.5 ) | wd( 8,1, 27.5 ) | wd( 8,0, 27.5 ) | wd( 3,8, 27.5 ); 3824 \end{cfa} 3825 \begin{cfa}[showspaces=true,aboveskip=0pt,belowskip=0pt] 3826 27.®500® 27.®5® 28. 27.®50000000® 3827 \end{cfa} 3828 For the C-string type, ©precision© is the maximum number of printed characters, so the string is truncared if it exceeds the maximum. 3829 \begin{cfa}[belowskip=0pt] 3830 sout | wd( 6,8, "abcd" ) | wd( 6,8, "abcdefghijk" ) | wd( 6,3, "abcd" ); 3831 \end{cfa} 3832 \begin{cfa}[showspaces=true,aboveskip=0pt,belowskip=0pt] 3833 abcd abcdefgh abc 3834 \end{cfa} 3835 3836 \item 3837 \Indexc{ws( unsigned char minimum, unsigned char significant, floating-point )}\index{manipulator!ws@©ws©} 3838 For floating-point type, ©minimum© is the same as for manipulator ©wd©, but ©significant© is the maximum number of significant digits to be printed for both the integer and fractions (versus only the fraction for ©wd©). 3839 If a value's significant digits is greater than ©significant©, the last significant digit is rounded up. 3840 \begin{cfa}[belowskip=0pt] 3841 sout | ws(6,6, 234.567) | ws(6,5, 234.567) | ws(6,4, 234.567) | ws(6,3, 234.567); 3842 \end{cfa} 3843 \begin{cfa}[showspaces=true,aboveskip=0pt,belowskip=0pt] 3844 234.567 234.5®7® 234.®6® 23®5® 3845 \end{cfa} 3846 If a value's magnitude is greater than ©significant©, the value is printed in scientific notation with the specified number of significant digits. 3847 \begin{cfa}[belowskip=0pt] 3848 sout | ws(6,6, 234567.) | ws(6,5, 234567.) | ws(6,4, 234567.) | ws(6,3, 234567.); 3849 \end{cfa} 3850 \begin{cfa}[showspaces=true,aboveskip=0pt,belowskip=0pt] 3851 234567. 2.3457®e+05® 2.346®e+05® 2.35®e+05® 3852 \end{cfa} 3853 If ©significant© is greater than ©minimum©, it defines the number of printed characters. 3854 \begin{cfa}[belowskip=0pt] 3855 sout | ws(3,6, 234567.) | ws(4,6, 234567.) | ws(5,6, 234567.) | ws(6,6, 234567.); 3856 \end{cfa} 3857 \begin{cfa}[showspaces=true,aboveskip=0pt,belowskip=0pt] 3858 234567. 234567. 234567. 234567. 3859 \end{cfa} 3860 3861 \item 3862 \Indexc{left}( field-width )\index{manipulator!left@©left©} left justify within the given field. 3863 \begin{cfa}[belowskip=0pt] 3864 sout | left(wd(4, 27)) | left(wd(10, 27.)) | left(wd(10, 27.5)) | left(wd(4,3, 27)) | left(wd(10,3, 27.5)); 3865 \end{cfa} 3866 \begin{cfa}[showspaces=true,aboveskip=0pt,belowskip=0pt] 3867 27® ® 27.000000 27.500000 027 27.500® ® 3868 \end{cfa} 3869 3870 \item 3871 \Indexc{pad0}( field-width )\index{manipulator!pad0@©pad0©} left pad with zeroes (0). 3872 \begin{cfa}[belowskip=0pt] 3873 sout | pad0( wd( 4, 27 ) ) | pad0( wd( 4,3, 27 ) ) | pad0( wd( 8,3, 27.5 ) ); 3874 ®00®27 ®0®27 ®00®27.500 3597 3875 \end{cfa} 3598 3876 \end{enumerate} … … 3655 3933 3656 3934 3935 \subsection{Input Value Manipulators} 3936 3937 The format of numeric input values in the same as C constants without a trailing type suffix, as the input value-type is denoted by the input variable. 3938 For ©_Bool© type, the constants are ©true© and ©false©. 3939 For integral types, any number of digits, optionally preceded by a sign (©+© or ©-©), where a 3940 \begin{itemize} 3941 \item 3942 ©1©-©9© prefix introduces a decimal value (©0©-©9©), 3943 \item 3944 ©0© prefix introduces an octal value (©0©-©7©), and 3945 \item 3946 ©0x© or ©0X© prefix introduces a hexadecimal value (©0©-©f©) with lower or upper case letters. 3947 \end{itemize} 3948 For floating-point types, any number of decimal digits, optionally preceded by a sign (©+© or ©-©), optionally containing a decimal point, and optionally followed by an exponent, ©e© or ©E©, with signed (optional) decimal digits. 3949 Floating-point values can also be written in hexadecimal format preceded by ©0x© or ©0X© with hexadecimal digits and exponent denoted by ©p© or ©P©. 3950 3951 For the C-string type, the input values are \emph{not} the same as C-string constants, \ie double quotes bracketing arbitrary text with escape sequences. 3952 Instead, the next sequence of non-whitespace characters are read, and the input sequence is terminated with delimiter ©'\0'©. 3953 The string variable \emph{must} be large enough to contain the input sequence. 3954 3955 The following \Index{manipulator}s control formatting of input values (reading), and only affect the format of the argument. 3956 3957 \begin{enumerate} 3958 \item 3959 \Indexc{skip( const char * pattern )}\index{manipulator!skip@©skip©} / ©skip( unsigned int length )© / ©const char * pattern© 3960 The argument defines a ©pattern© or ©length©. 3961 The ©pattern© is composed of white-space and non-white-space characters, where \emph{any} white-space character matches 0 or more input white-space characters (hence, consecutive white-space characters in the pattern are combined), and each non-white-space character matches exactly with an input character. 3962 The ©length© is composed of the next $N$ characters, including the newline character. 3963 If the match successes, the input characters are discarded, and input continues with the next character. 3964 If the match fails, the input characters are left unread. 3965 \begin{cfa}[belowskip=0pt] 3966 char sk[$\,$] = "abc"; 3967 sin | "abc " | skip( sk ) | skip( 5 ); // match input sequence 3968 \end{cfa} 3969 \begin{cfa}[showspaces=true,aboveskip=0pt,belowskip=0pt] 3970 ®abc ® 3971 ®abc ® 3972 ®xx® 3973 \end{cfa} 3974 3975 \item 3976 \Indexc{wdi}©( unsigned int maximum, T & val )©\index{manipulator!wdi@©wdi©} 3977 For all types except ©char©, ©maximum© is the maximum number of characters read for the current operation. 3978 \begin{cfa}[belowskip=0pt] 3979 char s[10]; int i; double d; 3980 sin | wdi( 4, s ) | wdi( 3, i ) | wdi( 8, d ); // c == "abcd", i == 123, d == 3.456E+2 3981 \end{cfa} 3982 \begin{cfa}[showspaces=true,aboveskip=0pt,belowskip=0pt] 3983 ®abcd1233.456E+2® 3984 \end{cfa} 3985 Note, input ©wdi© cannot be overloaded with output ©wd© because both have the same parameters but return different types. 3986 Currently, \CFA cannot distinguish between these two manipulators in the middle of an ©sout©/©sin© expression based on return type. 3987 3988 \item 3989 \Indexc{ignore( T & val )}\index{manipulator!ignore@©ignore©} 3990 For all types, the data is read from the stream depending on the argument type but ignored, \ie it is not stored in the argument. 3991 \begin{cfa}[belowskip=0pt] 3992 double d; 3993 sin | ignore( d ); // d is unchanged 3994 \end{cfa} 3995 \begin{cfa}[showspaces=true,aboveskip=0pt,belowskip=0pt] 3996 ® -75.35e-4® 25 3997 \end{cfa} 3998 3999 \item 4000 \Indexc{incl( const char * scanset, char * s )}\index{manipulator!incl@©incl©} 4001 For the C-string type, the argument defines a ©scanset© that matches any number of characters \emph{in} the set. 4002 Matching characters are read into the C string and null terminated. 4003 \begin{cfa}[belowskip=0pt] 4004 char s[10]; 4005 sin | incl( "abc", s ); 4006 \end{cfa} 4007 \begin{cfa}[showspaces=true,aboveskip=0pt,belowskip=0pt] 4008 ®bca®xyz 4009 \end{cfa} 4010 4011 \item 4012 \Indexc{excl( const char * scanset, char * s )}\index{manipulator!excl@©excl©} 4013 For the C-string type, the argument defines a ©scanset© that matches any number of characters \emph{not in} the set. 4014 Non-matching characters are read into the C string and null terminated. 4015 \begin{cfa}[belowskip=0pt] 4016 char s[10]; 4017 sin | excl( "abc", s ); 4018 \end{cfa} 4019 \begin{cfa}[showspaces=true,aboveskip=0pt,belowskip=0pt] 4020 ®xyz®bca 4021 \end{cfa} 4022 \end{enumerate} 4023 4024 3657 4025 \section{Types} 3658 4026 … … 4022 4390 \begin{itemize} 4023 4391 \item 4024 preventing having to determine or writelong generic types,4025 \item 4026 ensur esecondary variables, related to a primary variable, always have the same type.4392 not determining or writing long generic types, 4393 \item 4394 ensuring secondary variables, related to a primary variable, always have the same type. 4027 4395 \end{itemize} 4028 4396 … … 4046 4414 There is also the conundrum in type inferencing of when to \emph{\Index{brand}} a type. 4047 4415 That is, when is the type of the variable more important than the type of its initialization expression. 4048 For example, if a change is made in an initialization expression, it can cause significantcascading type changes and/or errors.4416 For example, if a change is made in an initialization expression, it can cause cascading type changes and/or errors. 4049 4417 At some point, a variable type needs to remain constant and the expression to be in error when it changes. 4050 4418 … … 4279 4647 4280 4648 coroutine Fibonacci { 4281 int fn; 4649 int fn; §\C{// used for communication}§ 4282 4650 }; 4283 4651 void ?{}( Fibonacci * this ) { … … 4285 4653 } 4286 4654 void main( Fibonacci * this ) { 4287 int fn1, fn2; 4288 this->fn = 0; 4655 int fn1, fn2; §\C{// retained between resumes}§ 4656 this->fn = 0; §\C{// case 0}§ 4289 4657 fn1 = this->fn; 4290 suspend(); 4291 4292 this->fn = 1; 4658 suspend(); §\C{// return to last resume}§ 4659 4660 this->fn = 1; §\C{// case 1}§ 4293 4661 fn2 = fn1; 4294 4662 fn1 = this->fn; 4295 suspend(); 4296 4297 for ( ;; ) { 4663 suspend(); §\C{// return to last resume}§ 4664 4665 for ( ;; ) { §\C{// general case}§ 4298 4666 this->fn = fn1 + fn2; 4299 4667 fn2 = fn1; 4300 4668 fn1 = this->fn; 4301 suspend(); 4669 suspend(); §\C{// return to last resume}§ 4302 4670 } // for 4303 4671 } 4304 4672 int next( Fibonacci * this ) { 4305 resume( this ); 4673 resume( this ); §\C{// transfer to last suspend}§ 4306 4674 return this->fn; 4307 4675 } … … 5848 6216 In \CFA, there are ambiguous cases with dereference and operator identifiers, \eg ©int *?*?()©, where the string ©*?*?© can be interpreted as: 5849 6217 \begin{cfa} 5850 *?§\color{red}\textvisiblespace§*? 5851 *§\color{red}\textvisiblespace§?*? 6218 *?§\color{red}\textvisiblespace§*? §\C{// dereference operator, dereference operator}§ 6219 *§\color{red}\textvisiblespace§?*? §\C{// dereference, multiplication operator}§ 5852 6220 \end{cfa} 5853 6221 By default, the first interpretation is selected, which does not yield a meaningful parse. … … 5901 6269 \eg: 5902 6270 \begin{cfa} 5903 x; 5904 *y; 5905 f( p1, p2 ); 5906 g( p1, p2 ) int p1, p2; 6271 x; §\C{// int x}§ 6272 *y; §\C{// int *y}§ 6273 f( p1, p2 ); §\C{// int f( int p1, int p2 );}§ 6274 g( p1, p2 ) int p1, p2; §\C{// int g( int p1, int p2 );}§ 5907 6275 \end{cfa} 5908 6276 \CFA continues to support K\&R routine definitions: 5909 6277 \begin{cfa} 5910 f( a, b, c ) 5911 int a, b; char c 6278 f( a, b, c ) §\C{// default int return}§ 6279 int a, b; char c §\C{// K\&R parameter declarations}§ 5912 6280 { 5913 6281 ... … … 5928 6296 int rtn( int i ); 5929 6297 int rtn( char c ); 5930 rtn( 'x' ); 6298 rtn( 'x' ); §\C{// programmer expects 2nd rtn to be called}§ 5931 6299 \end{cfa} 5932 6300 \item[Rationale:] it is more intuitive for the call to ©rtn© to match the second version of definition of ©rtn© rather than the first. … … 5950 6318 \item[Change:] make string literals ©const©: 5951 6319 \begin{cfa} 5952 char * p = "abc"; 5953 char * q = expr ? "abc" : "de"; 6320 char * p = "abc"; §\C{// valid in C, deprecated in \CFA}§ 6321 char * q = expr ? "abc" : "de"; §\C{// valid in C, invalid in \CFA}§ 5954 6322 \end{cfa} 5955 6323 The type of a string literal is changed from ©[] char© to ©const [] char©. … … 5958 6326 \begin{cfa} 5959 6327 char * p = "abc"; 5960 p[0] = 'w'; 6328 p[0] = 'w'; §\C{// segment fault or change constant literal}§ 5961 6329 \end{cfa} 5962 6330 The same problem occurs when passing a string literal to a routine that changes its argument. … … 5970 6338 \item[Change:] remove \newterm{tentative definitions}, which only occurs at file scope: 5971 6339 \begin{cfa} 5972 int i; 5973 int *j = ®&i®; 5974 int i = 0; 6340 int i; §\C{// forward definition}§ 6341 int *j = ®&i®; §\C{// forward reference, valid in C, invalid in \CFA}§ 6342 int i = 0; §\C{// definition}§ 5975 6343 \end{cfa} 5976 6344 is valid in C, and invalid in \CFA because duplicate overloaded object definitions at the same scope level are disallowed. … … 5978 6346 \begin{cfa} 5979 6347 struct X { int i; struct X *next; }; 5980 static struct X a; 6348 static struct X a; §\C{// forward definition}§ 5981 6349 static struct X b = { 0, ®&a® };§\C{// forward reference, valid in C, invalid in \CFA}§ 5982 static struct X a = { 1, &b }; 6350 static struct X a = { 1, &b }; §\C{// definition}§ 5983 6351 \end{cfa} 5984 6352 \item[Rationale:] avoids having different initialization rules for builtin types and user-defined types. … … 5995 6363 struct Person { 5996 6364 enum ®Colour® { R, G, B }; §\C[7cm]{// nested type}§ 5997 struct Face { 5998 ®Colour® Eyes, Hair; 6365 struct Face { §\C{// nested type}§ 6366 ®Colour® Eyes, Hair; §\C{// type defined outside (1 level)}§ 5999 6367 }; 6000 ®.Colour® shirt; 6001 ®Colour® pants; 6002 Face looks[10]; 6368 ®.Colour® shirt; §\C{// type defined outside (top level)}§ 6369 ®Colour® pants; §\C{// type defined same level}§ 6370 Face looks[10]; §\C{// type defined same level}§ 6003 6371 }; 6004 ®Colour® c = R; 6372 ®Colour® c = R; §\C{// type/enum defined same level}§ 6005 6373 Person®.Colour® pc = Person®.®R;§\C{// type/enum defined inside}§ 6006 Person®.®Face pretty; 6374 Person®.®Face pretty; §\C{// type defined inside}\CRT§ 6007 6375 \end{cfa} 6008 6376 In C, the name of the nested types belongs to the same scope as the name of the outermost enclosing structure, \ie the nested types are hoisted to the scope of the outer-most type, which is not useful and confusing. … … 6021 6389 \item[Difficulty of converting:] Semantic transformation. To make the struct type name visible in the scope of the enclosing struct, the struct tag could be declared in the scope of the enclosing struct, before the enclosing struct is defined. Example: 6022 6390 \begin{cfa} 6023 struct Y; 6391 struct Y; §\C{// struct Y and struct X are at the same scope}§ 6024 6392 struct X { 6025 6393 struct Y { /* ... */ } y; … … 6036 6404 \begin{cfa} 6037 6405 void foo() { 6038 int * b = malloc( sizeof(int) ); 6039 char * c = b; 6406 int * b = malloc( sizeof(int) ); §\C{// implicitly convert void * to int *}§ 6407 char * c = b; §\C{// implicitly convert int * to void *, and then void * to char *}§ 6040 6408 } 6041 6409 \end{cfa} … … 6298 6666 \leavevmode 6299 6667 \begin{cfa}[aboveskip=0pt,belowskip=0pt] 6300 forall( otype T | { int ?<?( T, T ); } ) 6668 forall( otype T | { int ?<?( T, T ); } ) §\C{// location}§ 6301 6669 T * bsearch( T key, const T * arr, size_t dim );§\indexc{bsearch}§ 6302 6670 6303 forall( otype T | { int ?<?( T, T ); } ) 6671 forall( otype T | { int ?<?( T, T ); } ) §\C{// position}§ 6304 6672 unsigned int bsearch( T key, const T * arr, size_t dim ); 6305 6673 … … 6308 6676 6309 6677 forall( otype E | { int ?<?( E, E ); } ) { 6310 E * bsearch( E key, const E * vals, size_t dim );§\indexc{bsearch}§ 6678 E * bsearch( E key, const E * vals, size_t dim );§\indexc{bsearch}§ §\C{// location}§ 6311 6679 size_t bsearch( E key, const E * vals, size_t dim );§\C{// position}§ 6312 6680 E * bsearchl( E key, const E * vals, size_t dim );§\indexc{bsearchl}§ … … 6356 6724 void srandom( unsigned int seed );§\indexc{srandom}§ 6357 6725 char random( void );§\indexc{random}§ 6358 char random( char u ); 6359 char random( char l, char u ); 6726 char random( char u ); §\C{// [0,u)}§ 6727 char random( char l, char u ); §\C{// [l,u)}§ 6360 6728 int random( void ); 6361 int random( int u ); 6362 int random( int l, int u ); 6729 int random( int u ); §\C{// [0,u)}§ 6730 int random( int l, int u ); §\C{// [l,u)}§ 6363 6731 unsigned int random( void ); 6364 unsigned int random( unsigned int u ); 6732 unsigned int random( unsigned int u ); §\C{// [0,u)}§ 6365 6733 unsigned int random( unsigned int l, unsigned int u ); §\C{// [l,u)}§ 6366 6734 long int random( void ); 6367 long int random( long int u ); 6368 long int random( long int l, long int u ); 6735 long int random( long int u ); §\C{// [0,u)}§ 6736 long int random( long int l, long int u ); §\C{// [l,u)}§ 6369 6737 unsigned long int random( void ); 6370 6738 unsigned long int random( unsigned long int u ); §\C{// [0,u)}§ … … 6417 6785 [ int, long double ] remquo( long double, long double ); 6418 6786 6419 float div( float, float, int * );§\indexc{div}§ 6787 float div( float, float, int * );§\indexc{div}§ §\C{// alternative name for remquo}§ 6420 6788 double div( double, double, int * ); 6421 6789 long double div( long double, long double, int * ); … … 6573 6941 long double atan2( long double, long double ); 6574 6942 6575 float atan( float, float ); 6943 float atan( float, float ); §\C{// alternative name for atan2}§ 6576 6944 double atan( double, double );§\indexc{atan}§ 6577 6945 long double atan( long double, long double ); … … 6764 7132 \begin{cfa}[aboveskip=0pt,belowskip=0pt] 6765 7133 struct Duration { 6766 int64_t tv; 7134 int64_t tv; §\C{// nanoseconds}§ 6767 7135 }; 6768 7136 … … 6894 7262 \begin{cfa}[aboveskip=0pt,belowskip=0pt] 6895 7263 struct Time { 6896 uint64_t tv; 7264 uint64_t tv; §\C{// nanoseconds since UNIX epoch}§ 6897 7265 }; 6898 7266 … … 6965 7333 \begin{cfa}[aboveskip=0pt,belowskip=0pt] 6966 7334 struct Clock { 6967 Duration offset; 6968 int clocktype; 7335 Duration offset; §\C{// for virtual clock: contains offset from real-time}§ 7336 int clocktype; §\C{// implementation only -1 (virtual), CLOCK\_REALTIME}§ 6969 7337 }; 6970 7338 … … 6974 7342 void ?{}( Clock & clk, Duration adj ); 6975 7343 6976 Duration getResNsec(); 6977 Duration getRes(); 6978 6979 Time getTimeNsec(); 6980 Time getTime(); 7344 Duration getResNsec(); §\C{// with nanoseconds}§ 7345 Duration getRes(); §\C{// without nanoseconds}§ 7346 7347 Time getTimeNsec(); §\C{// with nanoseconds}§ 7348 Time getTime(); §\C{// without nanoseconds}§ 6981 7349 Time getTime( Clock & clk ); 6982 7350 Time ?()( Clock & clk ); … … 6994 7362 6995 7363 \begin{cfa} 6996 void ?{}( Int * this ); 7364 void ?{}( Int * this ); §\C{// constructor/destructor}§ 6997 7365 void ?{}( Int * this, Int init ); 6998 7366 void ?{}( Int * this, zero_t ); … … 7003 7371 void ^?{}( Int * this ); 7004 7372 7005 Int ?=?( Int * lhs, Int rhs ); 7373 Int ?=?( Int * lhs, Int rhs ); §\C{// assignment}§ 7006 7374 Int ?=?( Int * lhs, long int rhs ); 7007 7375 Int ?=?( Int * lhs, unsigned long int rhs ); … … 7020 7388 unsigned long int narrow( Int val ); 7021 7389 7022 int ?==?( Int oper1, Int oper2 ); 7390 int ?==?( Int oper1, Int oper2 ); §\C{// comparison}§ 7023 7391 int ?==?( Int oper1, long int oper2 ); 7024 7392 int ?==?( long int oper2, Int oper1 ); … … 7056 7424 int ?>=?( unsigned long int oper1, Int oper2 ); 7057 7425 7058 Int +?( Int oper ); 7426 Int +?( Int oper ); §\C{// arithmetic}§ 7059 7427 Int -?( Int oper ); 7060 7428 Int ~?( Int oper ); … … 7138 7506 Int ?>>=?( Int * lhs, mp_bitcnt_t shift ); 7139 7507 7140 Int abs( Int oper ); 7508 Int abs( Int oper ); §\C{// number functions}§ 7141 7509 Int fact( unsigned long int N ); 7142 7510 Int gcd( Int oper1, Int oper2 ); … … 7249 7617 // implementation 7250 7618 struct Rational {§\indexc{Rational}§ 7251 long int numerator, denominator; 7619 long int numerator, denominator; §\C{// invariant: denominator > 0}§ 7252 7620 }; // Rational 7253 7621 7254 Rational rational(); 7622 Rational rational(); §\C{// constructors}§ 7255 7623 Rational rational( long int n ); 7256 7624 Rational rational( long int n, long int d ); … … 7258 7626 void ?{}( Rational * r, one_t ); 7259 7627 7260 long int numerator( Rational r ); 7628 long int numerator( Rational r ); §\C{// numerator/denominator getter/setter}§ 7261 7629 long int numerator( Rational r, long int n ); 7262 7630 long int denominator( Rational r ); 7263 7631 long int denominator( Rational r, long int d ); 7264 7632 7265 int ?==?( Rational l, Rational r ); 7633 int ?==?( Rational l, Rational r ); §\C{// comparison}§ 7266 7634 int ?!=?( Rational l, Rational r ); 7267 7635 int ?<?( Rational l, Rational r ); … … 7270 7638 int ?>=?( Rational l, Rational r ); 7271 7639 7272 Rational -?( Rational r ); 7640 Rational -?( Rational r ); §\C{// arithmetic}§ 7273 7641 Rational ?+?( Rational l, Rational r ); 7274 7642 Rational ?-?( Rational l, Rational r ); … … 7276 7644 Rational ?/?( Rational l, Rational r ); 7277 7645 7278 double widen( Rational r ); 7646 double widen( Rational r ); §\C{// conversion}§ 7279 7647 Rational narrow( double f, long int md ); 7280 7648 -
libcfa/src/concurrency/coroutine.hfa
r18e683b rc1ea11b 10 10 // Created On : Mon Nov 28 12:27:26 2016 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Fri Mar 30 18:23:45 201813 // Update Count : 812 // Last Modified On : Fri Jun 21 17:49:39 2019 13 // Update Count : 9 14 14 // 15 15 … … 53 53 forall(dtype T | is_coroutine(T)) 54 54 void prime(T & cor); 55 56 static inline struct coroutine_desc * active_coroutine() { return TL_GET( this_thread )->curr_cor; } 55 57 56 58 //----------------------------------------------------------------------------- -
libcfa/src/concurrency/invoke.h
r18e683b rc1ea11b 10 10 // Created On : Tue Jan 17 12:27:26 2016 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Sat May 19 08:23:21 201813 // Update Count : 3112 // Last Modified On : Sat Jun 22 18:19:13 2019 13 // Update Count : 40 14 14 // 15 15 … … 46 46 #ifdef __cforall 47 47 extern "Cforall" { 48 static inline struct thread_desc * 49 static inline struct __condition_criterion_t * 48 static inline struct thread_desc *& get_next( struct thread_desc & this ); 49 static inline struct __condition_criterion_t *& get_next( struct __condition_criterion_t & this ); 50 50 51 51 extern thread_local struct KernelThreadData { … … 199 199 #ifdef __cforall 200 200 extern "Cforall" { 201 static inline struct coroutine_desc * active_coroutine() { return TL_GET( this_thread )->curr_cor; } 202 static inline struct thread_desc * active_thread () { return TL_GET( this_thread ); } 203 static inline struct processor * active_processor() { return TL_GET( this_processor ); } // UNSAFE 204 205 static inline thread_desc * & get_next( thread_desc & this ) { 201 static inline thread_desc *& get_next( thread_desc & this ) { 206 202 return this.next; 207 203 } … … 210 206 return this.node.[next, prev]; 211 207 } 212 213 static inline struct __condition_criterion_t * & get_next( struct __condition_criterion_t & this );214 208 215 209 static inline void ?{}(__monitor_group_t & this) { -
libcfa/src/concurrency/kernel.cfa
r18e683b rc1ea11b 10 10 // Created On : Tue Jan 17 12:27:26 2017 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Mon Apr 9 16:11:46 201813 // Update Count : 2 412 // Last Modified On : Thu Jun 20 17:21:23 2019 13 // Update Count : 25 14 14 // 15 15 … … 907 907 void doregister( cluster * cltr, thread_desc & thrd ) { 908 908 lock (cltr->thread_list_lock __cfaabi_dbg_ctx2); 909 cltr->nthreads += 1; 909 910 push_front(cltr->threads, thrd); 910 911 unlock (cltr->thread_list_lock); … … 914 915 lock (cltr->thread_list_lock __cfaabi_dbg_ctx2); 915 916 remove(cltr->threads, thrd ); 917 cltr->nthreads -= 1; 916 918 unlock(cltr->thread_list_lock); 917 919 } … … 919 921 void doregister( cluster * cltr, processor * proc ) { 920 922 lock (cltr->proc_list_lock __cfaabi_dbg_ctx2); 923 cltr->nprocessors += 1; 921 924 push_front(cltr->procs, *proc); 922 925 unlock (cltr->proc_list_lock); … … 926 929 lock (cltr->proc_list_lock __cfaabi_dbg_ctx2); 927 930 remove(cltr->procs, *proc ); 931 cltr->nprocessors -= 1; 928 932 unlock(cltr->proc_list_lock); 929 933 } -
libcfa/src/concurrency/kernel.hfa
r18e683b rc1ea11b 10 10 // Created On : Tue Jan 17 12:27:26 2017 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Tue Apr 10 14:46:49 201813 // Update Count : 1 012 // Last Modified On : Sat Jun 22 11:39:17 2019 13 // Update Count : 16 14 14 // 15 15 … … 91 91 this.lock = NULL; 92 92 } 93 static inline void ^?{}(FinishAction & this) {}93 static inline void ^?{}(FinishAction &) {} 94 94 95 95 // Processor … … 176 176 __dllist_t(struct processor) procs; 177 177 __dllist_t(struct processor) idles; 178 179 // List of processors 178 unsigned int nprocessors; 179 180 // List of threads 180 181 __spinlock_t thread_list_lock; 181 182 __dllist_t(struct thread_desc) threads; 183 unsigned int nthreads; 182 184 183 185 // Link lists fields … … 200 202 } 201 203 204 static inline struct processor * active_processor() { return TL_GET( this_processor ); } // UNSAFE 205 static inline struct cluster * active_cluster () { return TL_GET( this_processor )->cltr; } 206 202 207 // Local Variables: // 203 208 // mode: c // -
libcfa/src/concurrency/thread.hfa
r18e683b rc1ea11b 10 10 // Created On : Tue Jan 17 12:27:26 2017 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Thu Mar 29 14:07:11 201813 // Update Count : 412 // Last Modified On : Fri Jun 21 17:51:33 2019 13 // Update Count : 5 14 14 // 15 15 … … 91 91 void yield( unsigned times ); 92 92 93 static inline struct thread_desc * active_thread () { return TL_GET( this_thread ); } 94 93 95 // Local Variables: // 94 96 // mode: c // -
src/ResolvExpr/Cost.h
r18e683b rc1ea11b 10 10 // Created On : Sun May 17 09:39:50 2015 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Mon Apr 29 18:33:44201913 // Update Count : 4912 // Last Modified On : Fri Jun 21 11:39:13 2019 13 // Update Count : 63 14 14 // 15 15 … … 21 21 22 22 namespace ResolvExpr { 23 #if 024 25 //*************************** OLD ***************************26 27 class Cost {28 private:29 Cost( int unsafeCost, int polyCost, int safeCost, int signCost,30 int varCost, int specCost, int referenceCost );31 public:32 Cost & incUnsafe( int inc = 1 );33 Cost & incPoly( int inc = 1 );34 Cost & incSafe( int inc = 1 );35 Cost & incSign( int inc = 1 );36 Cost & incVar( int inc = 1 );37 Cost & decSpec( int inc = 1 );38 Cost & incReference( int inc = 1 );39 40 int get_unsafeCost() const { return unsafeCost; }41 int get_polyCost() const { return polyCost; }42 int get_safeCost() const { return safeCost; }43 int get_signCost() const { return signCost; }44 int get_varCost() const { return varCost; }45 int get_specCost() const { return specCost; }46 int get_referenceCost() const { return referenceCost; }47 48 Cost operator+( const Cost &other ) const;49 Cost &operator+=( const Cost &other );50 bool operator<( const Cost &other ) const;51 bool operator==( const Cost &other ) const;52 bool operator!=( const Cost &other ) const;53 friend std::ostream &operator<<( std::ostream &os, const Cost &cost );54 // returns negative for *this < other, 0 for *this == other, positive for *this > other55 int compare( const Cost &other ) const;56 57 static const Cost zero;58 static const Cost infinity;59 60 static const Cost unsafe;61 static const Cost poly;62 static const Cost safe;63 static const Cost sign;64 static const Cost var;65 static const Cost spec;66 static const Cost reference;67 68 private:69 int unsafeCost; ///< Unsafe (narrowing) conversions70 int polyCost; ///< Count of parameters and return values bound to some poly type71 int safeCost; ///< Safe (widening) conversions72 int signCost; ///< Count of safe sign conversions73 int varCost; ///< Count of polymorphic type variables74 int specCost; ///< Polymorphic type specializations (type assertions), negative cost75 int referenceCost; ///< reference conversions76 };77 78 inline Cost::Cost( int unsafeCost, int polyCost, int safeCost, int signCost,79 int varCost, int specCost, int referenceCost )80 : unsafeCost( unsafeCost ), polyCost( polyCost ), safeCost( safeCost ), signCost( signCost ),81 varCost( varCost ), specCost( specCost ), referenceCost( referenceCost ) {}82 83 inline Cost & Cost::incUnsafe( int inc ) {84 if ( *this == infinity ) return *this;85 unsafeCost += inc;86 return *this;87 }88 89 inline Cost & Cost::incPoly( int inc ) {90 if ( *this == infinity ) return *this;91 polyCost += inc;92 return *this;93 }94 95 inline Cost & Cost::incSafe( int inc ) {96 if ( *this == infinity ) return *this;97 safeCost += inc;98 return *this;99 }100 101 inline Cost & Cost::incSign( int inc ) {102 if ( *this == infinity ) return *this;103 signCost += inc;104 return *this;105 }106 107 inline Cost & Cost::incVar( int inc ) {108 if ( *this == infinity ) return *this;109 varCost += inc;110 return *this;111 }112 113 inline Cost& Cost::decSpec( int dec ) {114 if ( *this == infinity ) return *this;115 specCost -= dec;116 return *this;117 }118 119 inline Cost & Cost::incReference( int inc ) {120 if ( *this == infinity ) return *this;121 referenceCost += inc;122 return *this;123 }124 125 inline Cost Cost::operator+( const Cost &other ) const {126 if ( *this == infinity || other == infinity ) return infinity;127 return Cost{128 unsafeCost + other.unsafeCost, polyCost + other.polyCost, safeCost + other.safeCost,129 signCost + other.signCost, varCost + other.varCost, specCost + other.specCost,130 referenceCost + other.referenceCost };131 }132 133 inline Cost &Cost::operator+=( const Cost &other ) {134 if ( *this == infinity ) return *this;135 if ( other == infinity ) {136 *this = infinity;137 return *this;138 }139 unsafeCost += other.unsafeCost;140 polyCost += other.polyCost;141 safeCost += other.safeCost;142 signCost += other.signCost;143 varCost += other.varCost;144 specCost += other.specCost;145 referenceCost += other.referenceCost;146 return *this;147 }148 149 inline bool Cost::operator<( const Cost &other ) const {150 if ( *this == infinity ) return false;151 if ( other == infinity ) return true;152 153 if ( unsafeCost > other.unsafeCost ) {154 return false;155 } else if ( unsafeCost < other.unsafeCost ) {156 return true;157 } else if ( polyCost > other.polyCost ) {158 return false;159 } else if ( polyCost < other.polyCost ) {160 return true;161 } else if ( safeCost > other.safeCost ) {162 return false;163 } else if ( safeCost < other.safeCost ) {164 return true;165 } else if ( signCost > other.signCost ) {166 return false;167 } else if ( signCost < other.signCost ) {168 return true;169 } else if ( varCost > other.varCost ) {170 return false;171 } else if ( varCost < other.varCost ) {172 return true;173 } else if ( specCost > other.specCost ) {174 return false;175 } else if ( specCost > other.specCost ) {176 return true;177 } else if ( referenceCost > other.referenceCost ) {178 return false;179 } else if ( referenceCost < other.referenceCost ) {180 return true;181 } else {182 return false;183 } // if184 }185 186 inline int Cost::compare( const Cost &other ) const {187 if ( *this == infinity ) return +1;188 if ( other == infinity ) return -1;189 190 int c = unsafeCost - other.unsafeCost; if ( c ) return c;191 c = polyCost - other.polyCost; if ( c ) return c;192 c = safeCost - other.safeCost; if ( c ) return c;193 c = signCost - other.signCost; if ( c ) return c;194 c = varCost - other.varCost; if ( c ) return c;195 c = specCost - other.specCost; if ( c ) return c;196 return referenceCost - other.referenceCost;197 }198 199 inline bool Cost::operator==( const Cost &other ) const {200 return unsafeCost == other.unsafeCost201 && polyCost == other.polyCost202 && safeCost == other.safeCost203 && signCost == other.signCost204 && varCost == other.varCost205 && specCost == other.specCost206 && referenceCost == other.referenceCost;207 }208 209 inline bool Cost::operator!=( const Cost &other ) const {210 return !( *this == other );211 }212 213 inline std::ostream &operator<<( std::ostream &os, const Cost &cost ) {214 return os << "( " << cost.unsafeCost << ", " << cost.polyCost << ", "215 << cost.safeCost << ", " << cost.signCost << ", "216 << cost.varCost << ", " << cost.specCost << ", "217 << cost.referenceCost << " )";218 }219 220 #else221 222 //*************************** NEW ***************************223 224 23 // To maximize performance and space, the 7 resolution costs are packed into a single 64-bit word. However, the 225 24 // specialization cost is a negative value so a correction is needed is a few places. … … 371 170 << ", " << cost.get_referenceCost() << " )"; 372 171 } 373 #endif // 0374 172 } // namespace ResolvExpr 375 173 -
tests/concurrent/examples/boundedBufferTHREAD.cfa
r18e683b rc1ea11b 5 5 // file "LICENCE" distributed with Cforall. 6 6 // 7 // boundedBuffer EXT.c --7 // boundedBufferTHREAD.c -- 8 8 // 9 9 // Author : Peter A. Buhr 10 10 // Created On : Wed Apr 18 22:52:12 2018 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Fri Jun 21 08:15:58201913 // Update Count : 2 312 // Last Modified On : Fri Jun 21 11:50:12 2019 13 // Update Count : 24 14 14 // 15 15 -
tools/stat.py
r18e683b rc1ea11b 11 11 content = f.readlines() 12 12 content = [x.strip() for x in content] 13 content = [ int(x) for x in content]14 content.remove(max(content)) 15 content.remove(min(content)) 16 med = numpy. around( numpy.median(content), decimals=1)17 avg = numpy. around( numpy.mean (content), decimals=2)18 std = numpy. around( numpy.std (content), decimals=2)19 print "median {0 } avg {1} stddev {2}".format( med, avg, std )13 content = [float(x) for x in content] # expect floating-point strings 14 content.remove(max(content)) # need at least 4 data values because 15 content.remove(min(content)) # the max and min values are removed 16 med = numpy.median(content) 17 avg = numpy.mean (content) 18 std = numpy.std (content) 19 print "median {0:.1f} avg {1:.1f} stddev {2:.2f}".format( med, avg, std ) 20 20 21 21
Note: See TracChangeset
for help on using the changeset viewer.