Changes in / [c1ea11b:18e683b]
- Files:
-
- 4 deleted
- 49 edited
-
benchmark/Makefile.am (modified) (14 diffs)
-
benchmark/Makefile.in (modified) (10 diffs)
-
benchmark/bench.h (modified) (1 diff)
-
benchmark/creation/cfa_cor.cfa (modified) (2 diffs)
-
benchmark/creation/cfa_thrd.cfa (modified) (2 diffs)
-
benchmark/creation/pthreads.c (modified) (1 diff)
-
benchmark/creation/qthreads.c (deleted)
-
benchmark/creation/upp_cor.cc (modified) (1 diff)
-
benchmark/creation/upp_thrd.cc (modified) (1 diff)
-
benchmark/ctxswitch/cfa_cor.cfa (modified) (3 diffs)
-
benchmark/ctxswitch/cfa_cor_then.cfa (modified) (3 diffs)
-
benchmark/ctxswitch/cfa_gen.cfa (deleted)
-
benchmark/ctxswitch/cfa_thrd.cfa (modified) (3 diffs)
-
benchmark/ctxswitch/cfa_thrd2.cfa (modified) (3 diffs)
-
benchmark/ctxswitch/kos_fibre.cpp (modified) (1 diff)
-
benchmark/ctxswitch/kos_fibre2.cpp (modified) (1 diff)
-
benchmark/ctxswitch/pthreads.c (modified) (1 diff)
-
benchmark/ctxswitch/qthreads.c (deleted)
-
benchmark/ctxswitch/upp_cor.cc (modified) (1 diff)
-
benchmark/ctxswitch/upp_thrd.cc (modified) (1 diff)
-
benchmark/fetch_add.c (modified) (1 diff)
-
benchmark/function.c (modified) (1 diff)
-
benchmark/loop.c (modified) (1 diff)
-
benchmark/mutex/cfa1.cfa (modified) (2 diffs)
-
benchmark/mutex/cfa2.cfa (modified) (2 diffs)
-
benchmark/mutex/cfa4.cfa (modified) (2 diffs)
-
benchmark/mutex/pthreads.c (modified) (1 diff)
-
benchmark/mutex/upp.cc (modified) (1 diff)
-
benchmark/schedext/cfa1.cfa (modified) (4 diffs)
-
benchmark/schedext/cfa2.cfa (modified) (4 diffs)
-
benchmark/schedext/cfa4.cfa (modified) (4 diffs)
-
benchmark/schedext/upp.cc (modified) (1 diff)
-
benchmark/schedint/cfa1.cfa (modified) (4 diffs)
-
benchmark/schedint/cfa2.cfa (modified) (4 diffs)
-
benchmark/schedint/cfa4.cfa (modified) (4 diffs)
-
benchmark/schedint/pthreads.c (modified) (3 diffs)
-
benchmark/schedint/upp.cc (modified) (2 diffs)
-
benchmark/tls-fetch_add.c (modified) (1 diff)
-
benchmark/ttst_lock.c (deleted)
-
doc/bibliography/pl.bib (modified) (6 diffs)
-
doc/papers/AMA/AMA-stix/ama/WileyNJD-v2.cls (modified) (1 diff)
-
doc/papers/concurrency/Paper.tex (modified) (40 diffs)
-
doc/papers/concurrency/annex/local.bib (modified) (1 diff)
-
doc/papers/concurrency/examples/Fib.cfa (modified) (2 diffs)
-
doc/user/user.tex (modified) (146 diffs)
-
libcfa/src/concurrency/coroutine.hfa (modified) (2 diffs)
-
libcfa/src/concurrency/invoke.h (modified) (4 diffs)
-
libcfa/src/concurrency/kernel.cfa (modified) (5 diffs)
-
libcfa/src/concurrency/kernel.hfa (modified) (4 diffs)
-
libcfa/src/concurrency/thread.hfa (modified) (2 diffs)
-
src/ResolvExpr/Cost.h (modified) (3 diffs)
-
tests/concurrent/examples/boundedBufferTHREAD.cfa (modified) (1 diff)
-
tools/stat.py (modified) (1 diff)
Legend:
- Unmodified
- Added
- Removed
-
benchmark/Makefile.am
rc1ea11b r18e683b 11 11 ## Created On : Sun May 31 09:08:15 2015 12 12 ## Last Modified By : Peter A. Buhr 13 ## Last Modified On : Sun Jun 23 12:34:29 201914 ## Update Count : 5213 ## Last Modified On : Tue Nov 6 09:01:23 2018 14 ## Update Count : 26 15 15 ############################################################################### 16 16 … … 21 21 include $(top_srcdir)/src/cfa.make 22 22 23 AM_CFLAGS = -O2 -Wall -Wextra - I$(srcdir) -lrt -pthread # -Werror23 AM_CFLAGS = -O2 -Wall -Wextra -Werror -I$(srcdir) -lrt -pthread 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))34 33 35 34 __quiet = verbose … … 46 45 __bench_v_JAVAC_verbose = $(AM_V_JAVAC) 47 46 __bench_v_UPP_verbose = $(AM_V_UPP) 48 __bench_v_QTHREAD_verbose = $(AM_V_CC) 47 49 48 50 49 … … 52 51 REPEAT = ${abs_top_builddir}/tools/repeat 53 52 STATS = ${abs_top_srcdir}/tools/stat.py 54 repeats = 3 # 3053 repeats = 30 55 54 skipcompile = no 56 55 TIME_FORMAT = "%E" … … 125 124 126 125 ctxswitch.csv: 127 @echo "generator,coroutine,thread" > $@ 128 @+make ctxswitch-cfa_generator.runquiet >> $@ && echo -n ',' >> $@ 126 @echo "coroutine,thread" > $@ 129 127 @+make ctxswitch-cfa_coroutine.runquiet >> $@ && echo -n ',' >> $@ 130 128 @+make ctxswitch-cfa_thread.runquiet >> $@ … … 155 153 $(BENCH_V_CC)$(COMPILE) -DBENCH_N=500000000 $(srcdir)/fetch_add.c 156 154 157 ttst_lock$(EXEEXT):158 $(BENCH_V_CC)$(COMPILE) -DBENCH_N=500000000 $(srcdir)/ttst_lock.c159 160 155 tls-fetch_add$(EXEEXT): 161 156 $(BENCH_V_CC)$(COMPILE) -DBENCH_N=500000000 $(srcdir)/tls-fetch_add.c … … 166 161 function.run \ 167 162 fetch_add.run \ 168 ttst_lock.run \169 163 tls-fetch_add.run \ 170 164 ctxswitch-pthread.run \ 171 ctxswitch-cfa_generator.run \172 165 ctxswitch-cfa_coroutine.run \ 173 166 ctxswitch-cfa_thread.run \ … … 176 169 ctxswitch-upp_thread.run \ 177 170 ctxswitch-goroutine.run \ 178 ctxswitch-java_thread.run \ 179 ctxswitch-qthreads.run 180 171 ctxswitch-java_thread.run 181 172 182 173 if WITH_LIBFIBRE … … 197 188 ctxswitch-pthread$(EXEEXT): 198 189 $(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.cfa202 190 203 191 ctxswitch-cfa_coroutine$(EXEEXT): … … 224 212 @echo "java JavaThread" >> a.out 225 213 @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 -lqthread229 214 230 215 ## ========================================================================================================= … … 320 305 creation-upp_thread.run \ 321 306 creation-goroutine.run \ 322 creation-java_thread.run \ 323 creation-qthreads.run 307 creation-java_thread.run 324 308 325 309 creation-cfa_coroutine$(EXEEXT): … … 349 333 @echo "java JavaThread" >> a.out 350 334 @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 -lqthread354 335 355 336 ## ========================================================================================================= … … 394 375 compile-typeof$(EXEEXT): 395 376 @$(CFACOMPILE) -fsyntax-only -w $(testdir)/typeof.cfa 377 -
benchmark/Makefile.in
rc1ea11b r18e683b 371 371 372 372 # applies to both programs 373 AM_CFLAGS = -O2 -Wall -Wextra - I$(srcdir) -lrt -pthread # -Werror373 AM_CFLAGS = -O2 -Wall -Wextra -Werror -I$(srcdir) -lrt -pthread 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))383 382 __quiet = verbose 384 383 __bench_v_CC_quiet = @ … … 394 393 __bench_v_JAVAC_verbose = $(AM_V_JAVAC) 395 394 __bench_v_UPP_verbose = $(AM_V_UPP) 396 __bench_v_QTHREAD_verbose = $(AM_V_CC)397 395 TOOLSDIR = ${abs_top_builddir}/tools/ 398 396 REPEAT = ${abs_top_builddir}/tools/repeat 399 397 STATS = ${abs_top_srcdir}/tools/stat.py 400 repeats = 3 # 30398 repeats = 30 401 399 skipcompile = no 402 400 TIME_FORMAT = "%E" … … 404 402 dummy_SOURCES = dummyC.c dummyCXX.cpp 405 403 FIX_NEW_LINES = cat $@ | tr "\n" "\t" | sed -r 's/\t,/,/' | tr "\t" "\n" > $@ 406 CTXSWITCH_DEPEND = loop.run function.run fetch_add.run ttst_lock.run\404 CTXSWITCH_DEPEND = loop.run function.run fetch_add.run \ 407 405 tls-fetch_add.run ctxswitch-pthread.run \ 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) 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) 413 410 testdir = $(top_srcdir)/tests 414 411 all: all-am … … 787 784 788 785 ctxswitch.csv: 789 @echo "generator,coroutine,thread" > $@ 790 @+make ctxswitch-cfa_generator.runquiet >> $@ && echo -n ',' >> $@ 786 @echo "coroutine,thread" > $@ 791 787 @+make ctxswitch-cfa_coroutine.runquiet >> $@ && echo -n ',' >> $@ 792 788 @+make ctxswitch-cfa_thread.runquiet >> $@ … … 816 812 $(BENCH_V_CC)$(COMPILE) -DBENCH_N=500000000 $(srcdir)/fetch_add.c 817 813 818 ttst_lock$(EXEEXT):819 $(BENCH_V_CC)$(COMPILE) -DBENCH_N=500000000 $(srcdir)/ttst_lock.c820 821 814 tls-fetch_add$(EXEEXT): 822 815 $(BENCH_V_CC)$(COMPILE) -DBENCH_N=500000000 $(srcdir)/tls-fetch_add.c … … 832 825 ctxswitch-pthread$(EXEEXT): 833 826 $(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.cfa837 827 838 828 ctxswitch-cfa_coroutine$(EXEEXT): … … 859 849 @echo "java JavaThread" >> a.out 860 850 @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 -lqthread864 851 865 852 mutex$(EXEEXT) :\ … … 950 937 creation-upp_thread.run \ 951 938 creation-goroutine.run \ 952 creation-java_thread.run \ 953 creation-qthreads.run 939 creation-java_thread.run 954 940 955 941 creation-cfa_coroutine$(EXEEXT): … … 979 965 @echo "java JavaThread" >> a.out 980 966 @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 -lqthread984 967 985 968 compile$(EXEEXT) :\ -
benchmark/bench.h
rc1ea11b r18e683b 45 45 statement; \ 46 46 EndTime = bench_time(); \ 47 doubleoutput = \48 (double)( EndTime - StartTime ) / n;47 unsigned long long int output = \ 48 ( EndTime - StartTime ) / n; 49 49 50 50 #if defined(__cforall) -
benchmark/creation/cfa_cor.cfa
rc1ea11b r18e683b 10 10 #endif 11 11 } 12 void main(MyCoroutine & ) {}12 void main(MyCoroutine & this) {} 13 13 14 14 int main(int argc, char* argv[]) { 15 15 BENCH( 16 for ( i; n) {16 for (size_t i = 0; i < n; i++) { 17 17 MyCoroutine m; 18 18 }, … … 20 20 ) 21 21 22 printf("% g\n", result);22 printf("%llu\n", result); 23 23 } -
benchmark/creation/cfa_thrd.cfa
rc1ea11b r18e683b 5 5 6 6 thread MyThread {}; 7 void main(MyThread & ) {}7 void main(MyThread & this) {} 8 8 9 9 int main(int argc, char* argv[]) { 10 10 BENCH( 11 for ( i; n) {11 for (size_t i = 0; i < n; i++) { 12 12 MyThread m; 13 13 }, … … 15 15 ) 16 16 17 printf("% g\n", result);17 printf("%llu\n", result); 18 18 } -
benchmark/creation/pthreads.c
rc1ea11b r18e683b 25 25 ) 26 26 27 printf("% g\n", result);27 printf("%llu\n", result); 28 28 } -
benchmark/creation/upp_cor.cc
rc1ea11b r18e683b 15 15 ) 16 16 17 printf("% g\n", result);17 printf("%llu\n", result); 18 18 } -
benchmark/creation/upp_thrd.cc
rc1ea11b r18e683b 15 15 ) 16 16 17 printf("% g\n", result);17 printf("%llu\n", result); 18 18 } -
benchmark/ctxswitch/cfa_cor.cfa
rc1ea11b r18e683b 1 #include <stdio.h> 1 2 #include <kernel.hfa> 2 3 #include <thread.hfa> … … 20 21 21 22 BENCH( 22 for ( i; n) {23 for (size_t i = 0; i < n; i++) { 23 24 resume( s ); 24 25 }, … … 26 27 ) 27 28 28 printf("% g\n", result);29 printf("%llu\n", result); 29 30 } -
benchmark/ctxswitch/cfa_cor_then.cfa
rc1ea11b r18e683b 1 #include <stdio.h> 1 2 #include <kernel.hfa> 2 3 #include <thread.hfa> … … 22 23 23 24 BENCH( 24 for ( i; n) {25 for (size_t i = 0; i < n; i++) { 25 26 resume( s ); 26 27 }, … … 28 29 ) 29 30 30 printf("% g\n", result);31 printf("%llu\n", result); 31 32 } -
benchmark/ctxswitch/cfa_thrd.cfa
rc1ea11b r18e683b 1 #include <stdio.h> 1 2 #include <thread.hfa> 2 3 … … 5 6 int main(int argc, char* argv[]) { 6 7 BENCH( 7 for ( i; n) {8 for (size_t i = 0; i < n; i++) { 8 9 yield(); 9 10 }, … … 11 12 ) 12 13 13 printf("% g\n", result);14 printf("%llu\n", result); 14 15 } -
benchmark/ctxswitch/cfa_thrd2.cfa
rc1ea11b r18e683b 1 #include <stdio.h> 1 2 #include <thread.hfa> 2 3 … … 16 17 Fibre f1; 17 18 BENCH( 18 for ( i; n) {19 for (size_t i = 0; i < n; i++) { 19 20 yield(); 20 21 }, … … 22 23 ) 23 24 24 printf("% g\n", result);25 printf("%llu\n", result); 25 26 done = true; 26 27 return 0; -
benchmark/ctxswitch/kos_fibre.cpp
rc1ea11b r18e683b 10 10 result 11 11 ) 12 printf("% g\n", result);12 printf("%llu\n", result); 13 13 return 0; 14 14 } -
benchmark/ctxswitch/kos_fibre2.cpp
rc1ea11b r18e683b 19 19 result 20 20 ) 21 printf("% g\n", result);21 printf("%llu\n", result); 22 22 done = true; 23 23 Fibre::yield(); -
benchmark/ctxswitch/pthreads.c
rc1ea11b r18e683b 14 14 ) 15 15 16 printf("% g\n", result);16 printf("%llu\n", result); 17 17 } -
benchmark/ctxswitch/upp_cor.cc
rc1ea11b r18e683b 30 30 ) 31 31 32 printf("% g\n", result);32 printf("%llu\n", result); 33 33 } -
benchmark/ctxswitch/upp_thrd.cc
rc1ea11b r18e683b 11 11 ) 12 12 13 printf("% g\n", result);13 printf("%llu\n", result); 14 14 } -
benchmark/fetch_add.c
rc1ea11b r18e683b 19 19 ) 20 20 21 printf("% g\n", result);21 printf("%llu\n", result); 22 22 } -
benchmark/function.c
rc1ea11b r18e683b 15 15 ) 16 16 17 printf("% g\n", result);17 printf("%llu\n", result); 18 18 } -
benchmark/loop.c
rc1ea11b r18e683b 11 11 ) 12 12 13 printf("% g\n", result);13 printf("%llu\n", result); 14 14 } -
benchmark/mutex/cfa1.cfa
rc1ea11b r18e683b 10 10 M m; 11 11 BENCH( 12 for ( i; n) {12 for (size_t i = 0; i < n; i++) { 13 13 call(m); 14 14 }, … … 16 16 ) 17 17 18 printf("% g\n", result);18 printf("%llu\n", result); 19 19 } -
benchmark/mutex/cfa2.cfa
rc1ea11b r18e683b 10 10 M m1, m2; 11 11 BENCH( 12 for ( i; n) {12 for (size_t i = 0; i < n; i++) { 13 13 call(m1, m2); 14 14 }, … … 16 16 ) 17 17 18 printf("% g\n", result);18 printf("%llu\n", result); 19 19 } -
benchmark/mutex/cfa4.cfa
rc1ea11b r18e683b 11 11 M m1, m2, m3, m4; 12 12 BENCH( 13 for ( i; n) {13 for (size_t i = 0; i < n; i++) { 14 14 call(m1, m2, m3, m4); 15 15 }, … … 17 17 ) 18 18 19 printf("% g\n", result);19 printf("%llu\n", result); 20 20 } -
benchmark/mutex/pthreads.c
rc1ea11b r18e683b 19 19 ) 20 20 21 printf("% g\n", result);21 printf("%llu\n", result); 22 22 } -
benchmark/mutex/upp.cc
rc1ea11b r18e683b 17 17 ) 18 18 19 printf("% g\n", result);19 printf("%llu\n", result); 20 20 } -
benchmark/schedext/cfa1.cfa
rc1ea11b r18e683b 18 18 go = 1; 19 19 BENCH( 20 for ( i; n) {20 for (size_t i = 0; i < n; i++) { 21 21 waitfor(call, a1); 22 22 }, … … 24 24 ) 25 25 26 printf("% g\n", result);26 printf("%llu\n", result); 27 27 go = 0; 28 28 return 0; … … 31 31 thread T {}; 32 32 void ^?{}( T & mutex this ) {} 33 void main( T & ) {33 void main( T & this ) { 34 34 while(go == 0) { yield(); } 35 35 while(go == 1) { call(m1); } … … 37 37 } 38 38 39 int main(__attribute__((unused)) int argc, __attribute__((unused)) char* argv[]) { 39 int main(int margc, char* margv[]) { 40 argc = margc; 41 argv = margv; 40 42 T t; 41 43 return wait(m1); -
benchmark/schedext/cfa2.cfa
rc1ea11b r18e683b 18 18 go = 1; 19 19 BENCH( 20 for ( i; n) {20 for (size_t i = 0; i < n; i++) { 21 21 waitfor(call, a1, a2); 22 22 }, … … 24 24 ) 25 25 26 printf("% g\n", result);26 printf("%llu\n", result); 27 27 go = 0; 28 28 return 0; … … 31 31 thread T {}; 32 32 void ^?{}( T & mutex this ) {} 33 void main( T & ) {33 void main( T & this ) { 34 34 while(go == 0) { yield(); } 35 35 while(go == 1) { call(m1, m2); } … … 37 37 } 38 38 39 int main(__attribute__((unused)) int argc, __attribute__((unused)) char* argv[]) { 39 int main(int margc, char* margv[]) { 40 argc = margc; 41 argv = margv; 40 42 T t; 41 43 return wait(m1, m2); -
benchmark/schedext/cfa4.cfa
rc1ea11b r18e683b 18 18 go = 1; 19 19 BENCH( 20 for ( i; n) {20 for (size_t i = 0; i < n; i++) { 21 21 waitfor(call, a1, a2, a3, a4); 22 22 }, … … 24 24 ) 25 25 26 printf("% g\n", result);26 printf("%llu\n", result); 27 27 go = 0; 28 28 return 0; … … 31 31 thread T {}; 32 32 void ^?{}( T & mutex this ) {} 33 void main( T & ) {33 void main( T & this ) { 34 34 while(go == 0) { yield(); } 35 35 while(go == 1) { call(m1, m2, m3, m4); } … … 37 37 } 38 38 39 int main(__attribute__((unused)) int argc, __attribute__((unused)) char* argv[]) { 39 int main(int margc, char* margv[]) { 40 argc = margc; 41 argv = margv; 40 42 T t; 41 43 return wait(m1, m2, m3, m4); -
benchmark/schedext/upp.cc
rc1ea11b r18e683b 20 20 ) 21 21 22 printf("% g\n", result);22 printf("%llu\n", result); 23 23 go = 0; 24 24 return 0; -
benchmark/schedint/cfa1.cfa
rc1ea11b r18e683b 21 21 go = 1; 22 22 BENCH( 23 for ( i; n) {23 for (size_t i = 0; i < n; i++) { 24 24 wait(c); 25 25 }, … … 27 27 ) 28 28 29 printf("% g\n", result);29 printf("%llu\n", result); 30 30 go = 0; 31 31 return 0; … … 33 33 34 34 thread T {}; 35 void ^?{}( T & mutex ) {}36 void main( T & ) {35 void ^?{}( T & mutex this ) {} 36 void main( T & this ) { 37 37 while(go == 0) { yield(); } 38 38 while(go == 1) { call(m1); } … … 40 40 } 41 41 42 int main(__attribute__((unused)) int argc, __attribute__((unused)) char* argv[]) { 42 int main(int margc, char* margv[]) { 43 argc = margc; 44 argv = margv; 43 45 T t; 44 46 return wait(m1); -
benchmark/schedint/cfa2.cfa
rc1ea11b r18e683b 21 21 go = 1; 22 22 BENCH( 23 for ( i; n) {23 for (size_t i = 0; i < n; i++) { 24 24 wait(c); 25 25 }, … … 27 27 ) 28 28 29 printf("% g\n", result);29 printf("%llu\n", result); 30 30 go = 0; 31 31 return 0; … … 34 34 thread T {}; 35 35 void ^?{}( T & mutex this ) {} 36 void main( T & ) {36 void main( T & this ) { 37 37 while(go == 0) { yield(); } 38 38 while(go == 1) { call(m1, m2); } … … 40 40 } 41 41 42 int main(__attribute__((unused)) int argc, __attribute__((unused)) char* argv[]) { 42 int main(int margc, char* margv[]) { 43 argc = margc; 44 argv = margv; 43 45 T t; 44 46 return wait(m1, m2); -
benchmark/schedint/cfa4.cfa
rc1ea11b r18e683b 21 21 go = 1; 22 22 BENCH( 23 for ( i; n) {23 for (size_t i = 0; i < n; i++) { 24 24 wait(c); 25 25 }, … … 27 27 ) 28 28 29 printf("% g\n", result);29 printf("%llu\n", result); 30 30 go = 0; 31 31 return 0; … … 34 34 thread T {}; 35 35 void ^?{}( T & mutex this ) {} 36 void main( T & ) {36 void main( T & this ) { 37 37 while(go == 0) { yield(); } 38 38 while(go == 1) { call(m1, m2, m3, m4); } … … 40 40 } 41 41 42 int main(__attribute__((unused)) int argc, __attribute__((unused)) char* argv[]) { 42 int main(int margc, char* margv[]) { 43 argc = margc; 44 argv = margv; 43 45 T t; 44 46 return wait(m1, m2, m3, m4); -
benchmark/schedint/pthreads.c
rc1ea11b r18e683b 27 27 ) 28 28 29 printf("% g\n", result);29 printf("%llu\n", result); 30 30 go = 0; 31 31 pthread_mutex_unlock(&m); … … 33 33 } 34 34 35 void* thread_main( __attribute__((unused)) void * arg) {35 void* thread_main(void * a) { 36 36 while(go == 0) { sched_yield(); } 37 37 while(go == 1) { call(); } … … 39 39 } 40 40 41 int main(__attribute__((unused)) int argc, __attribute__((unused)) char* argv[]) { 41 int main(int margc, char* margv[]) { 42 argc = margc; 43 argv = margv; 42 44 pthread_t thread; 43 45 if (pthread_create(&thread, NULL, thread_main, NULL) < 0) { -
benchmark/schedint/upp.cc
rc1ea11b r18e683b 23 23 ) 24 24 25 printf("% g\n", result);25 printf("%llu\n", result); 26 26 go = 0; 27 27 return 0; … … 39 39 }; 40 40 41 int main(__attribute__((unused)) int argc, __attribute__((unused)) char* argv[]) { 41 int main(int margc, char* margv[]) { 42 argc = margc; 43 argv = margv; 42 44 T t; 43 45 return m.wait(); -
benchmark/tls-fetch_add.c
rc1ea11b r18e683b 24 24 ) 25 25 26 printf("% g\n", result);26 printf("%llu\n", result); 27 27 } -
doc/bibliography/pl.bib
rc1ea11b r18e683b 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}},957 950 } 958 951 … … 1926 1919 year = 1965, 1927 1920 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}},1951 1921 } 1952 1922 … … 4389 4359 } 4390 4360 4391 4392 4361 @article{Liskov86, 4393 4362 keywords = {synchronous communication, concurrency}, … … 4402 4371 year = {}, 4403 4372 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}},4414 4373 } 4415 4374 … … 4534 4493 year = 2016, 4535 4494 howpublished= {\href{http://blog.reverberate.org/2016/01/making-arbitrarily-large-binaries-from.html} 4536 {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 }}, 4537 4498 optnote = {Accessed: 2016-09}, 4538 4499 } … … 4556 4517 trivial changes to the source code of the library. 4557 4518 } 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}},4568 4519 } 4569 4520 -
doc/papers/AMA/AMA-stix/ama/WileyNJD-v2.cls
rc1ea11b r18e683b 2444 2444 \@afterheading} 2445 2445 2446 \renewcommand\section{\@startsection{section}{1}{\z@}{-2 5pt \@plus -2pt \@minus -2pt}{12\p@}{\sectionfont}}%2447 \renewcommand\subsection{\@startsection{subsection}{2}{\z@}{-2 2pt \@plus -2pt \@minus -2pt}{5\p@}{\subsectionfont}}%2446 \renewcommand\section{\@startsection{section}{1}{\z@}{-27pt \@plus -2pt \@minus -2pt}{12\p@}{\sectionfont}}% 2447 \renewcommand\subsection{\@startsection{subsection}{2}{\z@}{-23pt \@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
rc1ea11b r18e683b 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, thread,159 otype, restrict, __restrict, __restrict__, __signed, __signed__, _Static_assert, suspend, 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- 9nor 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-8 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{ Adya02,vonBehren03}.315 As well, user-threading facilitates a simpler concurrency approach using thread objects that leverage sequential patterns versus events with call-backs~\cite{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 ) { 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 values615 int ?()( Fib & fib ) with( fib ) { return `resume( fib )`.fn; } // function-call interface 616 int ?()( Fib & fib, int N ) with( fib ) { for ( N - 1 ) `fib()`; return `fib()`; } // use simple interface 617 double ?()( Fib & fib ) with( fib ) { return (int)`fib()` / 3.14159; } // cast prevents recursive call 618 sout | (int)f1() | (double)f1() | f2( 2 ); // simple 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 ofthis kind of semantic programming requirement, if it results in very small, fast generators.630 As well, C programmers are not afraid with 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 , \eg LLVM has various coroutine support~\cite{CoroutineTS}, and \CFA can leverage this support should it fork @clang@.801 A compiler could also eliminate other artifacts in the generator simulation to further increase performance. 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 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. 1215 Our solution for coroutine termination works well for the most common asymmetric and symmetric coroutine usage-patterns. 1217 1216 For asymmetric coroutines, it is common for the first resumer (starter) coroutine to be the only resumer. 1218 1217 All previous generators converted to coroutines have this property. … … 1246 1245 1247 1246 1248 \subsection{ Generator /Coroutine Implementation}1247 \subsection{(Generator) Coroutine Implementation} 1249 1248 1250 1249 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. … … 1255 1254 class myCoroutine inherits baseCoroutine { ... } 1256 1255 \end{cfa} 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 thatsome 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.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. 1259 1258 Alternatives, such as explicitly starting threads as in Java, are repetitive and forgetting to call start is a common source of errors. 1260 1259 An alternative is composition: … … 1268 1267 However, there is nothing preventing wrong placement or multiple declarations. 1269 1268 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. 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. 1273 1270 The downside of this approach is that it makes custom types a special case in the language. 1274 1271 Users wanting to extend custom types or build their own can only do so in ways offered by the language. … … 1285 1282 \end{cfa} 1286 1283 Note, copying generators/coroutines/threads is not meaningful. 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.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. 1289 1286 Furthermore, two coroutines cannot logically execute on the same stack. 1290 1287 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. 1291 1288 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). 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 c oroutine descriptor from itshandle.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 currently executing coroutine handle. 1293 1290 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. 1294 1291 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@. … … 1496 1493 \end{tabular} 1497 1494 \end{cquote} 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 itshandle, and a special destructor to prevent deallocation while the thread is executing.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 thread handle, and a special destructor to prevent deallocation while the thread is executing. 1500 1497 (The qualifier @mutex@ for the destructor parameter is discussed in Section~\ref{s:Monitor}.) 1501 1498 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; … … 1620 1617 % 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. 1621 1618 % 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. 1622 Similarly, the function definitions ensures there is a mechanism to get (read) the monitor descriptor from itshandle, and a special destructor to prevent deallocation if a thread using the shared data.1619 Similarly, the function definitions ensures there is a mechanism to get (read) the currently executing monitor handle, and a special destructor to prevent deallocation if a thread using the shared data. 1623 1620 The custom monitor type also inserts any locks needed to implement the mutual exclusion semantics. 1624 1621 … … 1659 1656 called \newterm{bulk acquire}. 1660 1657 \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. 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.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. 1662 1659 A \CFA programmer only has to manage when to acquire mutual exclusion; 1663 1660 a \CC programmer must select the correct lock and acquisition mechanism from a panoply of locking options. … … 1803 1800 Figure~\ref{f:MonitorScheduling} shows general internal/external scheduling (for the bounded-buffer example in Figure~\ref{f:InternalExternalScheduling}). 1804 1801 External calling threads block on the calling queue, if the monitor is occupied, otherwise they enter in FIFO order. 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. 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. 1807 1803 1808 1804 There are three signalling mechanisms to unblock waiting threads to enter the monitor. 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.1805 Note, signalling cannot have the signaller and signalled thread in the monitor simultaneously because of the mutual exclusion so only one can proceed. 1810 1806 For internal scheduling, threads are unblocked from condition queues using @signal@, where the signallee is moved to urgent and the signaller continues (solid line). 1811 1807 Multiple signals move multiple signallees to urgent, until the condition is empty. … … 1847 1843 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. 1848 1844 In \CFA, a condition variable can be created/stored independently. 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.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. 1850 1846 1851 1847 % Signalling semantics cannot have the signaller and signalled thread in the monitor simultaneously, which means: … … 1856 1852 % The signalling thread continues and the signalled thread is marked for urgent unblocking at the next scheduling point (exit/wait). 1857 1853 % \item 1858 % The signalling thread blocks but is marked for urg ent unblocking at the next scheduling point and the signalled thread continues.1854 % The signalling thread blocks but is marked for urgrent unblocking at the next scheduling point and the signalled thread continues. 1859 1855 % \end{enumerate} 1860 1856 % The first approach is too restrictive, as it precludes solving a reasonable class of problems, \eg dating service (see Figure~\ref{f:DatingService}). … … 1965 1961 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. 1966 1962 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. 1967 Threads calling excluded functionsblock outside of (external to) the monitor on the calling queue, versus blocking on condition queues inside of (internal to) the monitor.1963 Calls threads to functions that are currently excluded block outside of (external to) the monitor on the calling queue, versus blocking on condition queues inside of (internal to) the monitor. 1968 1964 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@. 1969 1965 The writer does a similar action for each reader or writer using the resource. … … 2080 2076 For @wait( e )@, the default semantics is to atomically block the signaller and release all acquired mutex parameters, \ie @wait( e, m1, m2 )@. 2081 2077 To override the implicit multi-monitor wait, specific mutex parameter(s) can be specified, \eg @wait( e, m1 )@. 2082 Wait cannot statically verifies the released monitors are the acquired mutex-parameters without disallowing separately compiled helper functions calling @wait@.2078 Wait statically verifies the released monitors are the acquired mutex-parameters so unconditional release is safe. 2083 2079 While \CC supports bulk locking, @wait@ only accepts a single lock for a condition variable, so bulk locking with condition variables is asymmetric. 2084 2080 Finally, a signaller, … … 2092 2088 Similarly, for @waitfor( rtn )@, the default semantics is to atomically block the acceptor and release all acquired mutex parameters, \ie @waitfor( rtn, m1, m2 )@. 2093 2089 To override the implicit multi-monitor wait, specific mutex parameter(s) can be specified, \eg @waitfor( rtn, m1 )@. 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. 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. 2095 2092 % When an overloaded function appears in an @waitfor@ statement, calls to any function with that name are accepted. 2096 2093 % The rationale is that members with the same name should perform a similar function, and therefore, all should be eligible to accept a call. … … 2151 2148 The right example accepts either @mem1@ or @mem2@ if @C1@ and @C2@ are true. 2152 2149 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. 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. 2170 2163 2171 2164 … … 2364 2357 2365 2358 struct Msg { int i, j; }; 2366 thread Go Rtn { int i; float f; Msg m; };2367 void mem1( Go Rtn & mutex gortn, int i ) { gortn.i = i; }2368 void mem2( Go Rtn & mutex gortn, float f ) { gortn.f = f; }2369 void mem3( Go Rtn & mutex gortn, Msg m ) { gortn.m = m; }2370 void ^?{}( Go Rtn & mutex ) {}2371 2372 void main( Go Rtn & gortn ) with( gortn ) { // thread starts2359 thread Gortn { int i; float f; Msg m; }; 2360 void mem1( Gortn & mutex gortn, int i ) { gortn.i = i; } 2361 void mem2( Gortn & mutex gortn, float f ) { gortn.f = f; } 2362 void mem3( Gortn & mutex gortn, Msg m ) { gortn.m = m; } 2363 void ^?{}( Gortn & mutex ) {} 2364 2365 void main( Gortn & gortn ) with( gortn ) { // thread starts 2373 2366 2374 2367 for () { … … 2383 2376 } 2384 2377 int main() { 2385 Go Rtn gortn; $\C[2.0in]{// start thread}$2378 Gortn gortn; $\C[2.0in]{// start thread}$ 2386 2379 `mem1( gortn, 0 );` $\C{// different calls}\CRT$ 2387 2380 `mem2( gortn, 2.5 );` … … 2541 2534 % However, preemption is necessary for fairness and to reduce tail-latency. 2542 2535 % For concurrency that relies on spinning, if all cores spin the system is livelocked, whereas preemption breaks the livelock. 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} 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. 2599 2546 2600 2547 … … 2620 2567 The purpose of a cluster is to control the amount of parallelism that is possible among threads, plus scheduling and other execution defaults. 2621 2568 The default cluster-scheduler is single-queue multi-server, which provides automatic load-balancing of threads on processors. 2622 However, the design allows changing the scheduler, \eg multi-queue multi-serverwith work-stealing/sharing across the virtual processors.2569 However, the scheduler is pluggable, supporting alternative schedulers, such as multi-queue multi-server, with work-stealing/sharing across the virtual processors. 2623 2570 If several clusters exist, both threads and virtual processors, can be explicitly migrated from one cluster to another. 2624 2571 No automatic load balancing among clusters is performed by \CFA. … … 2627 2574 The user cluster is created to contain the application user-threads. 2628 2575 Having all threads execute on the one cluster often maximizes utilization of processors, which minimizes runtime. 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.2576 However, because of limitations of the underlying operating system, heterogeneous hardware, or scheduling requirements (real-time), multiple clusters are sometimes necessary. 2630 2577 2631 2578 … … 2671 2618 \subsection{Preemption} 2672 2619 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). 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. 2676 2622 Preemption is normally handled by setting a count-down timer on each virtual processor. 2677 2623 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. … … 2682 2628 Because preemption frequency is usually long (1 millisecond) performance cost is negligible. 2683 2629 2684 Linux switched a decade ago from specific to arbitrary process signal-delivery for applications with multiple kernel threads. 2630 However, on current Linux systems: 2685 2631 \begin{cquote} 2686 2632 A process-directed signal may be delivered to any one of the threads that does not currently have the signal blocked. … … 2688 2634 SIGNAL(7) - Linux Programmer's Manual 2689 2635 \end{cquote} 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.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. 2692 2638 Virtual processors register an expiration time with the discrete-event simulator, which is inserted in sorted order. 2693 2639 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. … … 2706 2652 2707 2653 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. 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.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. 2709 2655 2710 2656 \begin{comment} … … 2761 2707 \lstset{language=CFA,moredelim=**[is][\color{red}]{@}{@},deletedelim=**[is][]{`}{`}} 2762 2708 \begin{cfa} 2763 @thread@MyThread {};2764 void @main@( MyThread & ) {}2709 thread MyThread {}; 2710 void main( MyThread & ) {} 2765 2711 int main() { 2766 2712 BENCH( for ( N ) { @MyThread m;@ } ) … … 2804 2750 \lstset{language=CFA,moredelim=**[is][\color{red}]{@}{@},deletedelim=**[is][]{`}{`}} 2805 2751 \begin{cfa}[aboveskip=0pt,belowskip=0pt] 2806 @coroutine@C {} c;2752 coroutine C {} c; 2807 2753 void main( C & ) { for ( ;; ) { @suspend;@ } } 2808 2754 int main() { // coroutine test … … 2825 2771 \begin{tabular}{@{}r*{3}{D{.}{.}{3.2}}@{}} 2826 2772 \multicolumn{1}{@{}c}{} & \multicolumn{1}{c}{Median} &\multicolumn{1}{c}{Average} & \multicolumn{1}{c@{}}{Std Dev} \\ 2827 C function & 2 & 2 & 0 \\ 2828 \CFA generator & 2 & 2 & 0 \\ 2773 Kernel Thread & 333.5 & 332.96 & 4.1 \\ 2829 2774 \CFA Coroutine & 49 & 48.68 & 0.47 \\ 2830 2775 \CFA Thread & 105 & 105.57 & 1.37 \\ … … 2832 2777 \uC Thread & 100 & 99.29 & 0.96 \\ 2833 2778 Goroutine & 145 & 147.25 & 4.15 \\ 2834 Java Thread & 373.5 & 375.14 & 8.72 \\ 2835 Pthreads Thread & 333.5 & 332.96 & 4.1 2779 Java Thread & 373.5 & 375.14 & 8.72 2836 2780 \end{tabular} 2837 2781 \end{multicols} … … 2849 2793 \lstset{language=CFA,moredelim=**[is][\color{red}]{@}{@},deletedelim=**[is][]{`}{`}} 2850 2794 \begin{cfa} 2851 @monitor@M {} m1/*, m2, m3, m4*/;2795 monitor M {} m1/*, m2, m3, m4*/; 2852 2796 void __attribute__((noinline)) 2853 do_call( M & @mutex m/*, m2, m3, m4*/@) {}2797 do_call( M & mutex m/*, m2, m3, m4*/ ) {} 2854 2798 int main() { 2855 2799 BENCH( 2856 for( N ) do_call( m1/*, m2, m3, m4*/ );2800 for( N ) @do_call( m1/*, m2, m3, m4*/ );@ 2857 2801 ) 2858 2802 sout | result`ns; … … 2869 2813 \begin{tabular}{@{}r*{3}{D{.}{.}{3.2}}@{}} 2870 2814 \multicolumn{1}{@{}c}{} & \multicolumn{1}{c}{Median} &\multicolumn{1}{c}{Average} & \multicolumn{1}{c@{}}{Std Dev} \\ 2871 test and test-and-test lock & 26 & 26 & 0 \\ 2815 C function & 2 & 2 & 0 \\ 2816 FetchAdd + FetchSub & 26 & 26 & 0 \\ 2872 2817 Pthreads Mutex Lock & 31 & 31.71 & 0.97 \\ 2873 2818 \uC @monitor@ member rtn. & 31 & 31 & 0 \\ … … 2875 2820 \CFA @mutex@ function, 2 arg. & 84 & 85.36 & 1.99 \\ 2876 2821 \CFA @mutex@ function, 4 arg. & 158 & 161 & 4.22 \\ 2877 Java synchronized method& 27.5 & 29.79 & 2.932822 Java synchronized function & 27.5 & 29.79 & 2.93 2878 2823 \end{tabular} 2879 2824 \end{multicols} … … 2891 2836 \begin{cfa} 2892 2837 volatile int go = 0; 2893 @monitor@ M { @condition c;@} m;2838 monitor M { condition c; } m; 2894 2839 void __attribute__((noinline)) 2895 do_call( M & @mutex@a1 ) { @signal( c );@ }2840 do_call( M & mutex a1 ) { @signal( c );@ } 2896 2841 thread T {}; 2897 2842 void main( T & this ) { … … 2924 2869 \multicolumn{1}{@{}c}{} & \multicolumn{1}{c}{Median} & \multicolumn{1}{c}{Average} & \multicolumn{1}{c@{}}{Std Dev} \\ 2925 2870 Pthreads Cond. Variable & 6005 & 5681.43 & 835.45 \\ 2926 \uC @signal@ & 324 & 325.54 & 3 .02 \\2871 \uC @signal@ & 324 & 325.54 & 3,02 \\ 2927 2872 \CFA @signal@, 1 @monitor@ & 368.5 & 370.61 & 4.77 \\ 2928 2873 \CFA @signal@, 2 @monitor@ & 467 & 470.5 & 6.79 \\ … … 2944 2889 \begin{cfa} 2945 2890 volatile int go = 0; 2946 @monitor@M {} m;2891 monitor M {} m; 2947 2892 thread T {}; 2948 2893 void __attribute__((noinline)) 2949 do_call( M & @mutex@) {}2894 do_call( M & mutex ) {} 2950 2895 void main( T & ) { 2951 2896 while ( go == 0 ) { yield(); } 2952 while ( go == 1 ) { do_call( m );}2897 while ( go == 1 ) { @do_call( m );@ } 2953 2898 } 2954 2899 int __attribute__((noinline)) 2955 do_wait( M & @mutex@m ) {2900 do_wait( M & mutex m ) { 2956 2901 go = 1; // continue other thread 2957 2902 BENCH( for ( N ) { @waitfor( do_call, m );@ } ) -
doc/papers/concurrency/annex/local.bib
rc1ea11b r18e683b 66 66 } 67 67 68 @ misc{BankTransfer,68 @article{BankTransfer, 69 69 key = {Bank Transfer}, 70 70 keywords = {Bank Transfer}, 71 71 title = {Bank Account Transfer Problem}, 72 howpublished = {Wiki Wiki Web, \url{http://wiki.c2.com/?BankAccountTransferProblem}}, 72 publisher = {Wiki Wiki Web}, 73 address = {http://wiki.c2.com}, 73 74 year = 2010 74 75 } -
doc/papers/concurrency/examples/Fib.cfa
rc1ea11b r18e683b 13 13 } 14 14 15 #define FibCtor { 1, 0}16 typedef struct { int fn 1, fn; } Fib;17 int fib_state( Fib & f ) with( f) {18 int ret = fn; fn = fn1; fn1 = fn + ret;19 return ret;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; 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; // precompute first two states 35 [fn1, fn] = [1, 0]; 34 int fn1 = 1, fn2 = 0; // precompute first two states 36 35 for () { 36 fn = fn1 + fn2; fn2 = fn1; fn1 = fn; // general case 37 37 suspend(); // restart last resume 38 [fn1, fn] = [fn, fn + fn1];39 38 } 40 39 } 41 int ?()( Fib2 & fib ) { // function-call interface40 int ?()( Fib2 & fib ) with( fib ) { 42 41 return resume( fib ).fn; // restart last suspend 43 42 } 44 int ?()( Fib2 & fib, int N ) { // skip N values45 for ( N - 1 ) fib(); // use function-call interface43 int ?()( Fib2 & fib, int N ) with( fib ) { 44 for ( N - 1 ) fib(); 46 45 return fib(); 47 46 } 48 double ?()( Fib2 & fib ) { // different return type49 return (int)(fib()) / 3.14159; // cast prevents recursive call47 double ?()( Fib2 & fib ) with( fib ) { 48 return (int)(fib()) / 3.14159; // restart last suspend 50 49 } 51 50 -
doc/user/user.tex
rc1ea11b r18e683b 11 11 %% Created On : Wed Apr 6 14:53:29 2016 12 12 %% Last Modified By : Peter A. Buhr 13 %% Last Modified On : S at Jun 15 16:29:45201914 %% Update Count : 3 84713 %% Last Modified On : Sun May 5 18:24:50 2019 14 %% Update Count : 3489 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 ); §\C{// T is bound to int, forty\_two == 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 ); §\C{// search sorted array}§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 ); §\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}§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(); §\C{// select type and size from left-hand side}§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 ); } §\C{// use default C routine for 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}§ §\C{// C header file}§428 #include <stdio.h>§\indexc{stdio.h}§ §\C{// C header file}§ 429 429 #else 430 #include <fstream>§\indexc{fstream}§ §\C{// \CFA header file}§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; §\C{// make keyword an identifier}§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 ) §\C{// nesting ?}§526 #define with ®`®with®`® §\C{// make keyword an identifier}§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> §\C{// must have internal check for multiple expansion}§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; §\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}§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()® ) ... §\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}§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()® ) ... §\C{// x != 0}§620 while ( ®int x = f(), y = g()® ) ... §\C{// x != 0 \&\& y != 0}§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;® §\C{// unreachable initialization}§895 ®x = 7;® §\C{// unreachable code without label/branch}§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;® §\C{// unreachable initialization, cannot appear after case}§898 ®int z = 0;® §\C{// unreachable initialization, cannot appear after case}§ 899 899 z = 2; 900 900 case 1: 901 ®x = z;® §\C{// without fall through, z is uninitialized}§901 ®x = z;® §\C{// without fall through, z is uninitialized}§ 902 902 } 903 903 \end{cfa} … … 937 937 ®case 5: 938 938 ... 939 ®fallthru®; §\C{// explicit fall through}§939 ®fallthru®; §\C{// explicit fall through}§ 940 940 case 7: 941 941 ... 942 ®break® §\C{// explicit end of switch (redundant)}§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;® §\C{// allowed only at start}§963 ®int i = 0;® §\C{// allowed only at start}§ 964 964 case 0: 965 965 ... 966 ®int j = 0;® §\C{// disallowed}§966 ®int j = 0;® §\C{// disallowed}§ 967 967 case 1: 968 968 { 969 ®int k = 0;® §\C{// allowed at different nesting levels}§969 ®int k = 0;® §\C{// allowed at different nesting levels}§ 970 970 ... 971 ®case 2:® §\C{// disallow case in nested statements}§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:® §\C{// 1, 2, 3, 4, 5}§1021 case ®1~5:® §\C{// 1, 2, 3, 4, 5}§ 1022 1022 ... 1023 case ®10~15:® §\C{// 10, 11, 12, 13, 14, 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 { §\C{// aggregate}§1155 char c; §\C{// fields}§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; §\C{// access containing fields}§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; §\C{// fields}§1171 char c; §\C{// fields}§ 1172 1172 int i; 1173 1173 double d; 1174 void f() { §\C{// implicit ``this'' aggregate}§1175 ®this->®c; ®this->®i; ®this->®d; §\C{// access containing fields}§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 ) { §\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}§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 )® { §\C{// with statement}§1193 c; i; d; §\C{\color{red}// this.c, this.i, this.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 )® { §\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}§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; §\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}§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 ) { §\C{// constructor}§1239 ®s.i = i;® j = 3; m = 5.5; §\C{// initialize fields}§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 ) { ... } §\C{// ambiguous, same name and no context}§1259 with ( (S)w ) { ... } §\C{// unambiguous, cast}§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 ) { §\C{// implicit reference}§1264 % with ( sv ) { §\C{// implicit reference}§ 1265 1265 % S & sr = sv; 1266 % with ( sr ) { §\C{// explicit reference}§1266 % with ( sr ) { §\C{// explicit reference}§ 1267 1267 % S * sp = &sv; 1268 % with ( *sp ) { §\C{// computed reference}§1269 % i = 3; j = 4; §\C{\color{red}// sp--{\textgreater}i, sp--{\textgreater}j}§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; §\C{\color{red}// sr.i, sr.j}§1271 % i = 2; j = 3; §\C{\color{red}// sr.i, sr.j}§ 1272 1272 % } 1273 % i = 1; j = 2; §\C{\color{red}// sv.i, sv.j}§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() { §\C{\color{red}// implicit "this" parameter}§1282 i = 1; §\C{\color{red}// this->i}§1283 j = 2; §\C{\color{red}// this->j}§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® ) { §\C{// explicit "this" parameter}§1291 ®this.®i = 1; §\C{// "this" is not elided}§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 )® { §\C{// with clause}§1300 i = 1; §\C{\color{red}// this.i}§1301 j = 2; §\C{\color{red}// this.j}§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 )® { §\C{// with statement}§1318 ®with( s1 )® { §\C{// with statement}§ 1319 1319 // access fields of s1 without qualification 1320 ®with s2® { §\C{// nesting}§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 {}; §\C{// exception type}§1375 exception_t E {}; §\C{// exception type}§ 1376 1376 void f(...) { 1377 ... throw E{}; ... §\C{// termination}§1378 ... throwResume E{}; ... §\C{// resumption}§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®]® {...}; §\C{// definition}§1445 ... ®(*®f®())[®3®]® += 1; §\C{// usage}§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 // load address of x1652 ld r2,(r1) // load value of x1653 lda r3,104 // load address of y1654 st r2,(r3) // store x into y1651 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) // load value of x1660 1661 st r2,(104) // store x into y1659 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; // p1 points to x1676 p2 = p1; // p2 points to x1677 p1 = ®&®y; // p1 points to y1678 p3 = &p2; // p3 points to p21675 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; §\C{// compiler infers *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; §\C{// p1 = p2\ \ rather than\ \ *p1 = *p2}§1698 p2 = p1 + x; §\C{// p2 = p1 + x\ \ rather than\ \ *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; §\C{// pointer address assignment}§1703 ®*®p2 = ®*®p1 + x; §\C{// pointed-to value assignment / operation}§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; §\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}§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; §\C{// (\&*) cancel giving address in r1 not variable pointed-to by r1}§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; §\C{// (\&*) cancel giving address in r2, (\&(\&*)*) cancel giving address in r3}§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; §\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}§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; §\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}§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; §\C{// where 0 is the int * zero}§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; §\C{// unsound pointer dereference}§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; §\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}§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; §\C{// assign address of x}§1830 ®int * p = x;® §\C{// assign value of x}§1831 int & r = x; §\C{// must have address of 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 ); §\C{// reference parameter and return}§1841 z = f( x ) + f( y ); §\C{// reference operator added, temporaries needed for call results}§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 ); §\C{// compiler implicit generates temporaries}§1869 f( x + y ); g( ®&®(x + y) ); §\C{// compiler implicit generates temporaries}§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 ); §\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}§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; §\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}§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; §\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)}§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) 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; §\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§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) 1930 1930 \end{cfa} 1931 1931 … … 1940 1940 \begin{cfa} 1941 1941 int x; 1942 x + 1; §\C[2.0in]{// lvalue variable (int) converts to rvalue for expression}§1942 x + 1; // 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® ); §\C{// lvalue reference converts to rvalue}§1952 x = ®r® + f( ®r® ); // 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 ); §\C{// lvalue variable (int) convert to reference (int \&)}§1960 f( ®x® ); §\C{// lvalue variable (int) convert to reference (int \&)}§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 &) 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® ); §\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§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 &) 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(); §\C{// no input or output parameters}§2161 [ void ] g( void ); §\C{// no input or output parameters}§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) ); §\C{// foo is redefined as a parameter name}§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 * ); §\C{// returns an integer, accepts 2 pointers to integers}§2188 [ * int, int * ] f( int ); §\C{// returns 2 pointers to integers, accepts an integer}§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 ) ) ... §\C{// expands to int f( int (*p)[ 5 ] )}§2194 [ int ] f( ptoa( p, 5 ) ) ... §\C{// expands to [ int ] f( int (*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;® §\C{// implicitly return x, y}§2216 ®return;® §\C{// implicitly return x, y}§ 2217 2217 } 2218 2218 \end{cfa} … … 2224 2224 [ int x, int y ] f() { 2225 2225 ... 2226 } §\C{// implicitly return x, y}§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 } §\C{// implicitly return x, y}§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 ); §\C{// prototype declaration}§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 (); §\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}§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; §\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}§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; §\C{// routine name "f" is not allowed}§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 ); §\C{// rewrite $\Rightarrow$ p( 4, 7, 3 )}§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 ); §\C{// equivalent prototypes}§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 ) {} §\C{// match with this definition}§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 ); §\C{// 1st f}§2342 f( x : 7, y : 8.1 ); §\C{// 2nd f}§2343 f( 4, 5 ); §\C{// ambiguous call}§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 ); §\C{// ambiguous call ?}§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(); §\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 )}§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 ); §\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 )}§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 ); §\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}§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 ); §\C{// assume p( /* positional */, ... , /* named */ );}§2424 p( 1, z : 3, 4, 5, 6 ); §\C{// assume p( /* positional */, /* named */, ... );}§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 ); §\C{// rewrite $\Rightarrow$ p( 1, 2, 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; §\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}§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 , , ; §\C{// 3 unnamed fields}§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 ... §\C{// assign values to array ia}§2575 qsort( ia, size ); §\C{// sort ascending order using builtin ?<?}§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 ); §\C{// sort descending order by local redefinition}§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() { §\C{// int (* foo())( int )}§2586 [* [int]( int )] foo() { §\C{// int (* foo())( int )}§ 2587 2587 int ®i® = 7; 2588 2588 int bar( int p ) { 2589 ®i® += 1; §\C{// dependent on local variable}§2589 ®i® += 1; §\C{// dependent on local variable}§ 2590 2590 sout | ®i®; 2591 2591 } 2592 return bar; §\C{// undefined because of local dependence}§2592 return bar; §\C{// undefined because of local dependence}§ 2593 2593 } 2594 2594 int main() { 2595 * [int]( int ) fp = foo(); §\C{// int (* fp)( int )}§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® ); §\C{// element list}§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 ); §\C{// return quotient/remainder aggregate}§2626 printf( "%d %d\n", qr.quot, qr.rem ); §\C{// print quotient/remainder}§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 ); §\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}§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 ); §\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}§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 ); §\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}§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 ); §\C{// assign multiple variables}§2692 printf( "%d %d\n", quot, rem ); §\C{// print quotient/remainder}\CRT§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 ); §\C{// initialize tuple variable}§2719 printf( "%d %d\n", ®qr® ); §\C{// print quotient/remainder}§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; §\C{// assign multiple variables}§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; §\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}§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; §\C{// mass assignment}§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]; §\C{// multiple assignment}§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 ); §\C{// assignments in parameter list}§2866 f( [ c, a ] = [ b, d ] = 1.5 ); // 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 *); §\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}§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 constructors 2885 [S, S] y; // uses (1), (1), default constructor 2886 [S, S] z = x.0; // 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' ]; §\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 )}§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 ] ); §\C{// f( x.0, x.3 )}§2939 x.[ 0, 1 ] = x.[ 1, 0 ]; §\C{// [ x.0, x.1 ] = [ x.1, x.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 ]; §\C{// f() called once}§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(); §\C{// (1)}§2970 double f(); §\C{// (2)}§2971 2972 f(); §\C{// ambiguous - (1),(2) both equally viable}§2973 (int)f(); §\C{// choose (2)}§2969 int f(); // (1) 2970 double f(); // (2) 2971 2972 f(); // ambiguous - (1),(2) both equally viable 2973 (int)f(); // 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(); §\C{// valid, ignore results}§2982 (int)g(); §\C{// invalid, void cannot be converted to int}§2981 (void)f(); // valid, ignore results 2982 (int)g(); // invalid, void cannot be converted to int 2983 2983 2984 2984 struct A { int x; }; 2985 (struct A)f(); §\C{// invalid, int cannot be converted to A}§2985 (struct A)f(); // 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(); §\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}§3001 ([int, double])f(); // (1) valid 3002 ([int, int, int])g(); // (2) valid 3003 ([void, [int, int]])g(); // (3) valid 3004 ([int, int, int, int])g(); // (4) invalid 3005 ([int, [int, int, int]])g(); // (5) invalid 3006 3006 \end{cfa} 3007 3007 … … 3063 3063 void f([int, int], int, int); 3064 3064 3065 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}§3065 f([0, 0], 0, 0); // no cost 3066 f(0, 0, 0, 0); // cost for structuring 3067 f([0, 0,], [0, 0]); // cost for flattening 3068 f([0, 0, 0], 0); // cost for flattening and structuring 3069 3069 \end{cfa} 3070 3070 … … 3129 3129 [ unsigned int, char ] 3130 3130 [ double, double, double ] 3131 [ * int, int * ] §\C{// mix of CFA and ANSI}§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; §\C{// 2 element tuple, each element of type int}§3139 * [ char, char ] y; §\C{// pointer to a 2 element tuple}§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); §\C{// three input parameters of type int}§3157 [ void ] g ([ int, int, int ]); §\C{3 element tuple as input}§3156 [ void ] f (int, int, int); /* three input parameters of type int */ 3157 [ void ] g ([ int, int, int ]); /* 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 ]; §\C{// all four tuple coercions}§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++ ); §\C{// C routine call with side effects in arguments}§3326 [ v1, v2 ] = [ x++, x++ ]; §\C{// side effects in righthand side of multiple assignment}§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 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. 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. 3375 3357 \begin{cquote} 3376 3358 \begin{tabular}{@{}l@{\hspace{3em}}l@{}} … … 3391 3373 & 3392 3374 \begin{cfa}[showspaces=true,aboveskip=0pt,belowskip=0pt] 3393 1 ® ®2® ®33375 1 2 3 3394 3376 \end{cfa} 3395 3377 \end{tabular} 3396 3378 \end{cquote} 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 valueseparated by ``\lstinline[showspaces=true]@, @''.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 values separated by ``\lstinline[showspaces=true]@, @''. 3399 3381 \begin{cfa} 3400 3382 [int, [ int, int ] ] t1 = [ 1, [ 2, 3 ] ], t2 = [ 4, [ 5, 6 ] ]; 3401 sout | t1 | t2; §\C{// print tuples}§3383 sout | t1 | t2; §\C{// print tuples}§ 3402 3384 \end{cfa} 3403 3385 \begin{cfa}[showspaces=true,aboveskip=0pt] 3404 3386 1®, ®2®, ®3 4®, ®5®, ®6 3405 3387 \end{cfa} 3406 Finally, \CFA uses the logical-or operator for I/O as it is the lowest-priority \emph{overloadable}operator, other than assignment.3388 Finally, \CFA uses the logical-or operator for I/O as it is the lowest-priority overloadable operator, other than assignment. 3407 3389 Therefore, fewer output expressions require parenthesis. 3408 3390 \begin{cquote} … … 3411 3393 & 3412 3394 \begin{cfa} 3413 sout | x * 3 | y + 1 | z << 2 | x == y | ®(®x | y®)® | ®(®x || y®)® | ®(®x > z ? 1 : 2®)®;3395 sout | x * 3 | y + 1 | z << 2 | x == y | (x | y) | (x || y) | (x > z ? 1 : 2); 3414 3396 \end{cfa} 3415 3397 \\ … … 3417 3399 & 3418 3400 \begin{cfa} 3419 cout << x * 3 << y + 1 << ®(®z << 2®)® << ®(®x == y®)® << ®(®x | y®)® << ®(®x || y®)® << ®(®x > z ? 1 : 2®)®<< endl;3401 cout << x * 3 << y + 1 << ®(®z << 2®)® << ®(®x == y®)® << (x | y) << (x || y) << (x > z ? 1 : 2) << endl; 3420 3402 \end{cfa} 3421 3403 \\ … … 3426 3408 \end{tabular} 3427 3409 \end{cquote} 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 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. 3459 3411 3460 3412 3461 3413 \subsection{Implicit Separator} 3462 3414 3463 The \Index{implicit separator}\index{I/O!separator} character (space/blank) is a separator not a terminator for output.3415 The \Index{implicit separator}\index{I/O!separator} character (space/blank) is a separator not a terminator. 3464 3416 The rules for implicitly adding the separator are: 3465 3417 \begin{enumerate} … … 3489 3441 3490 3442 \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]@([{=$£¥¡¿«@ 3444 %$ 3445 \begin{cfa}[mathescape=off] 3446 sout | "x (" | 1 | "x [" | 2 | "x {" | 3 | "x =" | 4 | "x $" | 5 | "x £" | 6 | "x ¥" 3447 | 7 | "x ¡" | 8 | "x ¿" | 9 | "x «" | 10; 3448 \end{cfa} 3449 %$ 3450 \begin{cfa}[mathescape=off,basicstyle=\tt,showspaces=true,aboveskip=0pt,belowskip=0pt] 3451 x ®(®1 x ®[®2 x ®{®3 x ®=®4 x ®$®5 x ®£®6 x ®¥®7 x ®¡®8 x ®¿®9 x ®«®10 3452 \end{cfa} 3453 %$ 3454 where \lstinline[basicstyle=\tt]@¡¿@ are inverted opening exclamation and question marks, and \lstinline[basicstyle=\tt]@«@ is an opening citation mark. 3455 3456 \item 3491 3457 {\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]@,.;!?)]}%¢»@3458 A seperator does not appear after a C string ending with the (extended) \Index*{ASCII}\index{ASCII!extended} characters: \lstinline[basicstyle=\tt]@,.;!?)]}%¢»@ 3493 3459 \begin{cfa}[belowskip=0pt] 3494 3460 sout | 1 | ", x" | 2 | ". x" | 3 | "; x" | 4 | "! x" | 5 | "? x" | 6 | "% x" … … 3501 3467 3502 3468 \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]@([{=$£¥¡¿«@ 3504 %$ 3505 \begin{cfa}[mathescape=off] 3506 sout | "x (" | 1 | "x [" | 2 | "x {" | 3 | "x =" | 4 | "x $" | 5 | "x £" | 6 | "x ¥" 3507 | 7 | "x ¡" | 8 | "x ¿" | 9 | "x «" | 10; 3508 \end{cfa} 3509 %$ 3510 \begin{cfa}[mathescape=off,basicstyle=\tt,showspaces=true,aboveskip=0pt,belowskip=0pt] 3511 x ®(®1 x ®[®2 x ®{®3 x ®=®4 x ®$®5 x ®£®6 x ®¥®7 x ®¡®8 x ®¿®9 x ®«®10 3512 \end{cfa} 3513 %$ 3514 where \lstinline[basicstyle=\tt]@¡¿@ are inverted opening exclamation and question marks, and \lstinline[basicstyle=\tt]@«@ is an opening citation mark. 3515 3516 \item 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@ 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@ 3518 3470 \begin{cfa}[belowskip=0pt] 3519 3471 sout | "x`" | 1 | "`x'" | 2 | "'x\"" | 3 | "\"x:" | 4 | ":x " | 5 | " x\t" | 6 | "\tx"; … … 3534 3486 3535 3487 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©). 3488 \subsection{Manipulator} 3489 3490 The following \CC-style \Index{manipulator}s and routines control implicit seperation. 3540 3491 \begin{enumerate} 3541 3492 \item 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.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. 3543 3494 The separator string can be at most 16 characters including the ©'\0'© string terminator (15 printable characters). 3544 3495 \begin{cfa}[mathescape=off,belowskip=0pt] 3545 sepSet( sout, ", $" ); §\C{// set separator from " " to ", \$"}§3496 sepSet( sout, ", $" ); §\C{// set separator from " " to ", \$"}§ 3546 3497 sout | 1 | 2 | 3 | " \"" | ®sep® | "\""; 3547 3498 \end{cfa} … … 3552 3503 %$ 3553 3504 \begin{cfa}[belowskip=0pt] 3554 sepSet( sout, " " ); §\C{// reset separator to " "}§3505 sepSet( sout, " " ); §\C{// reset separator to " "}§ 3555 3506 sout | 1 | 2 | 3 | " \"" | ®sepGet( sout )® | "\""; 3556 3507 \end{cfa} … … 3560 3511 ©sepGet© can be used to store a separator and then restore it: 3561 3512 \begin{cfa}[belowskip=0pt] 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}§3513 char store[®sepSize®]; §\C{// sepSize is the maximum separator size}§ 3514 strcpy( store, sepGet( sout ) ); §\C{// copy current separator}§ 3515 sepSet( sout, "_" ); §\C{// change separator to underscore}§ 3565 3516 sout | 1 | 2 | 3; 3566 3517 \end{cfa} … … 3569 3520 \end{cfa} 3570 3521 \begin{cfa}[belowskip=0pt] 3571 sepSet( sout, store ); §\C{// change separator back to original}§3522 sepSet( sout, store ); §\C{// change separator back to original}§ 3572 3523 sout | 1 | 2 | 3; 3573 3524 \end{cfa} … … 3577 3528 3578 3529 \item 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.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. 3580 3531 The tuple separator-string can be at most 16 characters including the ©'\0'© string terminator (15 printable characters). 3581 3532 \begin{cfa}[belowskip=0pt] 3582 sepSetTuple( sout, " " ); §\C{// set tuple separator from ", " to " "}§3533 sepSetTuple( sout, " " ); §\C{// set tuple separator from ", " to " "}§ 3583 3534 sout | t1 | t2 | " \"" | ®sepTuple® | "\""; 3584 3535 \end{cfa} … … 3587 3538 \end{cfa} 3588 3539 \begin{cfa}[belowskip=0pt] 3589 sepSetTuple( sout, ", " ); §\C{// reset tuple separator to ", "}§3540 sepSetTuple( sout, ", " ); §\C{// reset tuple separator to ", "}§ 3590 3541 sout | t1 | t2 | " \"" | ®sepGetTuple( sout )® | "\""; 3591 3542 \end{cfa} … … 3596 3547 3597 3548 \item 3598 \Indexc{sepDisable}\index{manipulator!sepDisable@©sepDisable©} and \Indexc{sepEnable}\index{manipulator!sepEnable@©sepEnable©} toggle printing the separator.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. 3599 3550 \begin{cfa}[belowskip=0pt] 3600 sout | sepDisable | 1 | 2 | 3; §\C{//turn off implicit separator}§3551 sout | sepDisable | 1 | 2 | 3; §\C{// globally turn off implicit separator}§ 3601 3552 \end{cfa} 3602 3553 \begin{cfa}[showspaces=true,aboveskip=0pt,belowskip=0pt] … … 3604 3555 \end{cfa} 3605 3556 \begin{cfa}[belowskip=0pt] 3606 sout | sepEnable | 1 | 2 | 3; §\C{//turn on implicit separator}§3557 sout | sepEnable | 1 | 2 | 3; §\C{// globally turn on implicit separator}§ 3607 3558 \end{cfa} 3608 3559 \begin{cfa}[mathescape=off,showspaces=true,aboveskip=0pt,belowskip=0pt] … … 3611 3562 3612 3563 \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.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. 3614 3565 \begin{cfa}[belowskip=0pt] 3615 sout | 1 | sepOff | 2 | 3; §\C{// turn off implicit separator for the next item}§3566 sout | 1 | sepOff | 2 | 3; §\C{// locally turn off implicit separator}§ 3616 3567 \end{cfa} 3617 3568 \begin{cfa}[showspaces=true,aboveskip=0pt,belowskip=0pt] … … 3619 3570 \end{cfa} 3620 3571 \begin{cfa}[belowskip=0pt] 3621 sout | sepDisable | 1 | sepOn | 2 | 3; §\C{// turn on implicit separator for the next item}§3572 sout | sepDisable | 1 | sepOn | 2 | 3; §\C{// locally turn on implicit separator}§ 3622 3573 \end{cfa} 3623 3574 \begin{cfa}[showspaces=true,aboveskip=0pt,belowskip=0pt] … … 3626 3577 The tuple separator also responses to being turned on and off. 3627 3578 \begin{cfa}[belowskip=0pt] 3628 sout | t1 | sepOff | t2; §\C{// locally turn on/off implicit separator}§3579 sout | t1 | sepOff | t2; §\C{// locally turn on/off implicit separator}§ 3629 3580 \end{cfa} 3630 3581 \begin{cfa}[showspaces=true,aboveskip=0pt,belowskip=0pt] … … 3634 3585 use ©sep© to accomplish this functionality. 3635 3586 \begin{cfa}[belowskip=0pt] 3636 sout | sepOn | 1 | 2 | 3 | sepOn; §\C{// sepOn does nothing at start/end of line}§3587 sout | sepOn | 1 | 2 | 3 | sepOn; §\C{// sepOn does nothing at start/end of line}§ 3637 3588 \end{cfa} 3638 3589 \begin{cfa}[showspaces=true,aboveskip=0pt,belowskip=0pt] … … 3640 3591 \end{cfa} 3641 3592 \begin{cfa}[belowskip=0pt] 3642 sout | sep | 1 | 2 | 3 | sep ; §\C{// use sep to print separator at start/end of line}§3593 sout | sep | 1 | 2 | 3 | sep ; §\C{// use sep to print separator at start/end of line}§ 3643 3594 \end{cfa} 3644 3595 \begin{cfa}[showspaces=true,aboveskip=0pt,belowskip=0pt] 3645 3596 ® ®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 \item3657 \Indexc{nl}\index{manipulator!nl@©nl©} scans characters until the next newline character, i.e., ignore the remaining characters in the line.3658 \item3659 \Indexc{nlOn}\index{manipulator!nlOn@©nlOn©} reads the newline character, when reading single characters.3660 \item3661 \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 33668 \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 \item3674 \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 23683 33684 43685 53686 3687 63688 \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 newline3690 \item3691 \Indexc{nlOn}\index{manipulator!nlOn@©nlOn©} implicitly prints a newline at the end of each output expression.3692 \item3693 \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 \item3702 \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 0b110113706 sout | bin( -27HH ) | bin( -27H ) | bin( -27 ) | bin( -27L );3707 0b11100101 0b1111111111100101 0b11111111111111111111111111100101 0b(58 1s)1001013708 \end{cfa}3709 3710 \item3711 \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 0333715 sout | oct( -27HH ) | oct( -27H ) | oct( -27 ) | oct( -27L );3716 0345 0177745 037777777745 017777777777777777777453717 \end{cfa}3718 Note, octal 0 is \emph{not} preceded by ©0© to prevent confusion.3719 3720 \item3721 \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 0x1b3725 sout | hex( -27HH ) | hex( -27H ) | hex( -27 ) | hex( -27L );3726 0xe5 0xffe5 0xffffffe5 0xffffffffffffffe53727 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+13730 sout | hex( -27.5F ) | hex( -27.5 ) | hex( -27.5L );3731 -0x1.b8p+4 -0x1.b8p+4 -0xd.cp+13732 \end{cfa}3733 3734 \item3735 \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+013740 \end{cfa}3741 3742 \item3743 \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®+43747 \end{cfa}3748 3749 \item3750 \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 1b3754 \end{cfa}3755 3756 \item3757 \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.53762 \end{cfa}3763 3764 \item3765 \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.53769 \end{cfa}3770 3771 \item3772 \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 343782 ® ®4.000000 ® ®4.000000 4.0000003783 ® ®ab ® ®ab ab3784 ab ab ab3785 \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®343805 \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 34563812 \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®343820 \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 abc3834 \end{cfa}3835 3836 \item3837 \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 \item3862 \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 \item3871 \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.5003875 3597 \end{cfa} 3876 3598 \end{enumerate} … … 3933 3655 3934 3656 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 a3940 \begin{itemize}3941 \item3942 ©1©-©9© prefix introduces a decimal value (©0©-©9©),3943 \item3944 ©0© prefix introduces an octal value (©0©-©7©), and3945 \item3946 ©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 \item3959 \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 sequence3968 \end{cfa}3969 \begin{cfa}[showspaces=true,aboveskip=0pt,belowskip=0pt]3970 ®abc ®3971 ®abc ®3972 ®xx®3973 \end{cfa}3974 3975 \item3976 \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+23981 \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 \item3989 \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 unchanged3994 \end{cfa}3995 \begin{cfa}[showspaces=true,aboveskip=0pt,belowskip=0pt]3996 ® -75.35e-4® 253997 \end{cfa}3998 3999 \item4000 \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®xyz4009 \end{cfa}4010 4011 \item4012 \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®bca4021 \end{cfa}4022 \end{enumerate}4023 4024 4025 3657 \section{Types} 4026 3658 … … 4390 4022 \begin{itemize} 4391 4023 \item 4392 not determining or writinglong generic types,4393 \item 4394 ensur ingsecondary variables, related to a primary variable, always have the same type.4024 preventing having to determine or write long generic types, 4025 \item 4026 ensure secondary variables, related to a primary variable, always have the same type. 4395 4027 \end{itemize} 4396 4028 … … 4414 4046 There is also the conundrum in type inferencing of when to \emph{\Index{brand}} a type. 4415 4047 That is, when is the type of the variable more important than the type of its initialization expression. 4416 For example, if a change is made in an initialization expression, it can cause cascading type changes and/or errors.4048 For example, if a change is made in an initialization expression, it can cause significant cascading type changes and/or errors. 4417 4049 At some point, a variable type needs to remain constant and the expression to be in error when it changes. 4418 4050 … … 4647 4279 4648 4280 coroutine Fibonacci { 4649 int fn; §\C{// used for communication}§4281 int fn; §\C{// used for communication}§ 4650 4282 }; 4651 4283 void ?{}( Fibonacci * this ) { … … 4653 4285 } 4654 4286 void main( Fibonacci * this ) { 4655 int fn1, fn2; §\C{// retained between resumes}§4656 this->fn = 0; §\C{// case 0}§4287 int fn1, fn2; §\C{// retained between resumes}§ 4288 this->fn = 0; §\C{// case 0}§ 4657 4289 fn1 = this->fn; 4658 suspend(); §\C{// return to last resume}§4659 4660 this->fn = 1; §\C{// case 1}§4290 suspend(); §\C{// return to last resume}§ 4291 4292 this->fn = 1; §\C{// case 1}§ 4661 4293 fn2 = fn1; 4662 4294 fn1 = this->fn; 4663 suspend(); §\C{// return to last resume}§4664 4665 for ( ;; ) { §\C{// general case}§4295 suspend(); §\C{// return to last resume}§ 4296 4297 for ( ;; ) { §\C{// general case}§ 4666 4298 this->fn = fn1 + fn2; 4667 4299 fn2 = fn1; 4668 4300 fn1 = this->fn; 4669 suspend(); §\C{// return to last resume}§4301 suspend(); §\C{// return to last resume}§ 4670 4302 } // for 4671 4303 } 4672 4304 int next( Fibonacci * this ) { 4673 resume( this ); §\C{// transfer to last suspend}§4305 resume( this ); §\C{// transfer to last suspend}§ 4674 4306 return this->fn; 4675 4307 } … … 6216 5848 In \CFA, there are ambiguous cases with dereference and operator identifiers, \eg ©int *?*?()©, where the string ©*?*?© can be interpreted as: 6217 5849 \begin{cfa} 6218 *?§\color{red}\textvisiblespace§*? §\C{// dereference operator, dereference operator}§6219 *§\color{red}\textvisiblespace§?*? §\C{// dereference, multiplication operator}§5850 *?§\color{red}\textvisiblespace§*? §\C{// dereference operator, dereference operator}§ 5851 *§\color{red}\textvisiblespace§?*? §\C{// dereference, multiplication operator}§ 6220 5852 \end{cfa} 6221 5853 By default, the first interpretation is selected, which does not yield a meaningful parse. … … 6269 5901 \eg: 6270 5902 \begin{cfa} 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 );}§5903 x; §\C{// int x}§ 5904 *y; §\C{// int *y}§ 5905 f( p1, p2 ); §\C{// int f( int p1, int p2 );}§ 5906 g( p1, p2 ) int p1, p2; §\C{// int g( int p1, int p2 );}§ 6275 5907 \end{cfa} 6276 5908 \CFA continues to support K\&R routine definitions: 6277 5909 \begin{cfa} 6278 f( a, b, c ) §\C{// default int return}§6279 int a, b; char c §\C{// K\&R parameter declarations}§5910 f( a, b, c ) §\C{// default int return}§ 5911 int a, b; char c §\C{// K\&R parameter declarations}§ 6280 5912 { 6281 5913 ... … … 6296 5928 int rtn( int i ); 6297 5929 int rtn( char c ); 6298 rtn( 'x' ); §\C{// programmer expects 2nd rtn to be called}§5930 rtn( 'x' ); §\C{// programmer expects 2nd rtn to be called}§ 6299 5931 \end{cfa} 6300 5932 \item[Rationale:] it is more intuitive for the call to ©rtn© to match the second version of definition of ©rtn© rather than the first. … … 6318 5950 \item[Change:] make string literals ©const©: 6319 5951 \begin{cfa} 6320 char * p = "abc"; §\C{// valid in C, deprecated in \CFA}§6321 char * q = expr ? "abc" : "de"; §\C{// valid in C, invalid in \CFA}§5952 char * p = "abc"; §\C{// valid in C, deprecated in \CFA}§ 5953 char * q = expr ? "abc" : "de"; §\C{// valid in C, invalid in \CFA}§ 6322 5954 \end{cfa} 6323 5955 The type of a string literal is changed from ©[] char© to ©const [] char©. … … 6326 5958 \begin{cfa} 6327 5959 char * p = "abc"; 6328 p[0] = 'w'; §\C{// segment fault or change constant literal}§5960 p[0] = 'w'; §\C{// segment fault or change constant literal}§ 6329 5961 \end{cfa} 6330 5962 The same problem occurs when passing a string literal to a routine that changes its argument. … … 6338 5970 \item[Change:] remove \newterm{tentative definitions}, which only occurs at file scope: 6339 5971 \begin{cfa} 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}§5972 int i; §\C{// forward definition}§ 5973 int *j = ®&i®; §\C{// forward reference, valid in C, invalid in \CFA}§ 5974 int i = 0; §\C{// definition}§ 6343 5975 \end{cfa} 6344 5976 is valid in C, and invalid in \CFA because duplicate overloaded object definitions at the same scope level are disallowed. … … 6346 5978 \begin{cfa} 6347 5979 struct X { int i; struct X *next; }; 6348 static struct X a; §\C{// forward definition}§5980 static struct X a; §\C{// forward definition}§ 6349 5981 static struct X b = { 0, ®&a® };§\C{// forward reference, valid in C, invalid in \CFA}§ 6350 static struct X a = { 1, &b }; §\C{// definition}§5982 static struct X a = { 1, &b }; §\C{// definition}§ 6351 5983 \end{cfa} 6352 5984 \item[Rationale:] avoids having different initialization rules for builtin types and user-defined types. … … 6363 5995 struct Person { 6364 5996 enum ®Colour® { R, G, B }; §\C[7cm]{// nested type}§ 6365 struct Face { §\C{// nested type}§6366 ®Colour® Eyes, Hair; §\C{// type defined outside (1 level)}§5997 struct Face { §\C{// nested type}§ 5998 ®Colour® Eyes, Hair; §\C{// type defined outside (1 level)}§ 6367 5999 }; 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}§6000 ®.Colour® shirt; §\C{// type defined outside (top level)}§ 6001 ®Colour® pants; §\C{// type defined same level}§ 6002 Face looks[10]; §\C{// type defined same level}§ 6371 6003 }; 6372 ®Colour® c = R; §\C{// type/enum defined same level}§6004 ®Colour® c = R; §\C{// type/enum defined same level}§ 6373 6005 Person®.Colour® pc = Person®.®R;§\C{// type/enum defined inside}§ 6374 Person®.®Face pretty; §\C{// type defined inside}\CRT§6006 Person®.®Face pretty; §\C{// type defined inside}\CRT§ 6375 6007 \end{cfa} 6376 6008 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. … … 6389 6021 \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: 6390 6022 \begin{cfa} 6391 struct Y; §\C{// struct Y and struct X are at the same scope}§6023 struct Y; §\C{// struct Y and struct X are at the same scope}§ 6392 6024 struct X { 6393 6025 struct Y { /* ... */ } y; … … 6404 6036 \begin{cfa} 6405 6037 void foo() { 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 *}§6038 int * b = malloc( sizeof(int) ); §\C{// implicitly convert void * to int *}§ 6039 char * c = b; §\C{// implicitly convert int * to void *, and then void * to char *}§ 6408 6040 } 6409 6041 \end{cfa} … … 6666 6298 \leavevmode 6667 6299 \begin{cfa}[aboveskip=0pt,belowskip=0pt] 6668 forall( otype T | { int ?<?( T, T ); } ) §\C{// location}§6300 forall( otype T | { int ?<?( T, T ); } ) §\C{// location}§ 6669 6301 T * bsearch( T key, const T * arr, size_t dim );§\indexc{bsearch}§ 6670 6302 6671 forall( otype T | { int ?<?( T, T ); } ) §\C{// position}§6303 forall( otype T | { int ?<?( T, T ); } ) §\C{// position}§ 6672 6304 unsigned int bsearch( T key, const T * arr, size_t dim ); 6673 6305 … … 6676 6308 6677 6309 forall( otype E | { int ?<?( E, E ); } ) { 6678 E * bsearch( E key, const E * vals, size_t dim );§\indexc{bsearch}§ §\C{// location}§6310 E * bsearch( E key, const E * vals, size_t dim );§\indexc{bsearch}§ §\C{// location}§ 6679 6311 size_t bsearch( E key, const E * vals, size_t dim );§\C{// position}§ 6680 6312 E * bsearchl( E key, const E * vals, size_t dim );§\indexc{bsearchl}§ … … 6724 6356 void srandom( unsigned int seed );§\indexc{srandom}§ 6725 6357 char random( void );§\indexc{random}§ 6726 char random( char u ); §\C{// [0,u)}§6727 char random( char l, char u ); §\C{// [l,u)}§6358 char random( char u ); §\C{// [0,u)}§ 6359 char random( char l, char u ); §\C{// [l,u)}§ 6728 6360 int random( void ); 6729 int random( int u ); §\C{// [0,u)}§6730 int random( int l, int u ); §\C{// [l,u)}§6361 int random( int u ); §\C{// [0,u)}§ 6362 int random( int l, int u ); §\C{// [l,u)}§ 6731 6363 unsigned int random( void ); 6732 unsigned int random( unsigned int u ); §\C{// [0,u)}§6364 unsigned int random( unsigned int u ); §\C{// [0,u)}§ 6733 6365 unsigned int random( unsigned int l, unsigned int u ); §\C{// [l,u)}§ 6734 6366 long int random( void ); 6735 long int random( long int u ); §\C{// [0,u)}§6736 long int random( long int l, long int u ); §\C{// [l,u)}§6367 long int random( long int u ); §\C{// [0,u)}§ 6368 long int random( long int l, long int u ); §\C{// [l,u)}§ 6737 6369 unsigned long int random( void ); 6738 6370 unsigned long int random( unsigned long int u ); §\C{// [0,u)}§ … … 6785 6417 [ int, long double ] remquo( long double, long double ); 6786 6418 6787 float div( float, float, int * );§\indexc{div}§ §\C{// alternative name for remquo}§6419 float div( float, float, int * );§\indexc{div}§ §\C{// alternative name for remquo}§ 6788 6420 double div( double, double, int * ); 6789 6421 long double div( long double, long double, int * ); … … 6941 6573 long double atan2( long double, long double ); 6942 6574 6943 float atan( float, float ); §\C{// alternative name for atan2}§6575 float atan( float, float ); §\C{// alternative name for atan2}§ 6944 6576 double atan( double, double );§\indexc{atan}§ 6945 6577 long double atan( long double, long double ); … … 7132 6764 \begin{cfa}[aboveskip=0pt,belowskip=0pt] 7133 6765 struct Duration { 7134 int64_t tv; §\C{// nanoseconds}§6766 int64_t tv; §\C{// nanoseconds}§ 7135 6767 }; 7136 6768 … … 7262 6894 \begin{cfa}[aboveskip=0pt,belowskip=0pt] 7263 6895 struct Time { 7264 uint64_t tv; §\C{// nanoseconds since UNIX epoch}§6896 uint64_t tv; §\C{// nanoseconds since UNIX epoch}§ 7265 6897 }; 7266 6898 … … 7333 6965 \begin{cfa}[aboveskip=0pt,belowskip=0pt] 7334 6966 struct Clock { 7335 Duration offset; §\C{// for virtual clock: contains offset from real-time}§7336 int clocktype; §\C{// implementation only -1 (virtual), CLOCK\_REALTIME}§6967 Duration offset; §\C{// for virtual clock: contains offset from real-time}§ 6968 int clocktype; §\C{// implementation only -1 (virtual), CLOCK\_REALTIME}§ 7337 6969 }; 7338 6970 … … 7342 6974 void ?{}( Clock & clk, Duration adj ); 7343 6975 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}§6976 Duration getResNsec(); §\C{// with nanoseconds}§ 6977 Duration getRes(); §\C{// without nanoseconds}§ 6978 6979 Time getTimeNsec(); §\C{// with nanoseconds}§ 6980 Time getTime(); §\C{// without nanoseconds}§ 7349 6981 Time getTime( Clock & clk ); 7350 6982 Time ?()( Clock & clk ); … … 7362 6994 7363 6995 \begin{cfa} 7364 void ?{}( Int * this ); §\C{// constructor/destructor}§6996 void ?{}( Int * this ); §\C{// constructor/destructor}§ 7365 6997 void ?{}( Int * this, Int init ); 7366 6998 void ?{}( Int * this, zero_t ); … … 7371 7003 void ^?{}( Int * this ); 7372 7004 7373 Int ?=?( Int * lhs, Int rhs ); §\C{// assignment}§7005 Int ?=?( Int * lhs, Int rhs ); §\C{// assignment}§ 7374 7006 Int ?=?( Int * lhs, long int rhs ); 7375 7007 Int ?=?( Int * lhs, unsigned long int rhs ); … … 7388 7020 unsigned long int narrow( Int val ); 7389 7021 7390 int ?==?( Int oper1, Int oper2 ); §\C{// comparison}§7022 int ?==?( Int oper1, Int oper2 ); §\C{// comparison}§ 7391 7023 int ?==?( Int oper1, long int oper2 ); 7392 7024 int ?==?( long int oper2, Int oper1 ); … … 7424 7056 int ?>=?( unsigned long int oper1, Int oper2 ); 7425 7057 7426 Int +?( Int oper ); §\C{// arithmetic}§7058 Int +?( Int oper ); §\C{// arithmetic}§ 7427 7059 Int -?( Int oper ); 7428 7060 Int ~?( Int oper ); … … 7506 7138 Int ?>>=?( Int * lhs, mp_bitcnt_t shift ); 7507 7139 7508 Int abs( Int oper ); §\C{// number functions}§7140 Int abs( Int oper ); §\C{// number functions}§ 7509 7141 Int fact( unsigned long int N ); 7510 7142 Int gcd( Int oper1, Int oper2 ); … … 7617 7249 // implementation 7618 7250 struct Rational {§\indexc{Rational}§ 7619 long int numerator, denominator; §\C{// invariant: denominator > 0}§7251 long int numerator, denominator; §\C{// invariant: denominator > 0}§ 7620 7252 }; // Rational 7621 7253 7622 Rational rational(); §\C{// constructors}§7254 Rational rational(); §\C{// constructors}§ 7623 7255 Rational rational( long int n ); 7624 7256 Rational rational( long int n, long int d ); … … 7626 7258 void ?{}( Rational * r, one_t ); 7627 7259 7628 long int numerator( Rational r ); §\C{// numerator/denominator getter/setter}§7260 long int numerator( Rational r ); §\C{// numerator/denominator getter/setter}§ 7629 7261 long int numerator( Rational r, long int n ); 7630 7262 long int denominator( Rational r ); 7631 7263 long int denominator( Rational r, long int d ); 7632 7264 7633 int ?==?( Rational l, Rational r ); §\C{// comparison}§7265 int ?==?( Rational l, Rational r ); §\C{// comparison}§ 7634 7266 int ?!=?( Rational l, Rational r ); 7635 7267 int ?<?( Rational l, Rational r ); … … 7638 7270 int ?>=?( Rational l, Rational r ); 7639 7271 7640 Rational -?( Rational r ); §\C{// arithmetic}§7272 Rational -?( Rational r ); §\C{// arithmetic}§ 7641 7273 Rational ?+?( Rational l, Rational r ); 7642 7274 Rational ?-?( Rational l, Rational r ); … … 7644 7276 Rational ?/?( Rational l, Rational r ); 7645 7277 7646 double widen( Rational r ); §\C{// conversion}§7278 double widen( Rational r ); §\C{// conversion}§ 7647 7279 Rational narrow( double f, long int md ); 7648 7280 -
libcfa/src/concurrency/coroutine.hfa
rc1ea11b r18e683b 10 10 // Created On : Mon Nov 28 12:27:26 2016 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Fri Jun 21 17:49:39 201913 // Update Count : 912 // Last Modified On : Fri Mar 30 18:23:45 2018 13 // Update Count : 8 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; }57 55 58 56 //----------------------------------------------------------------------------- -
libcfa/src/concurrency/invoke.h
rc1ea11b r18e683b 10 10 // Created On : Tue Jan 17 12:27:26 2016 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Sat Jun 22 18:19:13 201913 // Update Count : 4012 // Last Modified On : Sat May 19 08:23:21 2018 13 // Update Count : 31 14 14 // 15 15 … … 46 46 #ifdef __cforall 47 47 extern "Cforall" { 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 );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 thread_desc *& get_next( thread_desc & this ) { 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 ) { 202 206 return this.next; 203 207 } … … 206 210 return this.node.[next, prev]; 207 211 } 212 213 static inline struct __condition_criterion_t * & get_next( struct __condition_criterion_t & this ); 208 214 209 215 static inline void ?{}(__monitor_group_t & this) { -
libcfa/src/concurrency/kernel.cfa
rc1ea11b r18e683b 10 10 // Created On : Tue Jan 17 12:27:26 2017 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Thu Jun 20 17:21:23 201913 // Update Count : 2 512 // Last Modified On : Mon Apr 9 16:11:46 2018 13 // Update Count : 24 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;910 909 push_front(cltr->threads, thrd); 911 910 unlock (cltr->thread_list_lock); … … 915 914 lock (cltr->thread_list_lock __cfaabi_dbg_ctx2); 916 915 remove(cltr->threads, thrd ); 917 cltr->nthreads -= 1;918 916 unlock(cltr->thread_list_lock); 919 917 } … … 921 919 void doregister( cluster * cltr, processor * proc ) { 922 920 lock (cltr->proc_list_lock __cfaabi_dbg_ctx2); 923 cltr->nprocessors += 1;924 921 push_front(cltr->procs, *proc); 925 922 unlock (cltr->proc_list_lock); … … 929 926 lock (cltr->proc_list_lock __cfaabi_dbg_ctx2); 930 927 remove(cltr->procs, *proc ); 931 cltr->nprocessors -= 1;932 928 unlock(cltr->proc_list_lock); 933 929 } -
libcfa/src/concurrency/kernel.hfa
rc1ea11b r18e683b 10 10 // Created On : Tue Jan 17 12:27:26 2017 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Sat Jun 22 11:39:17 201913 // Update Count : 1 612 // Last Modified On : Tue Apr 10 14:46:49 2018 13 // Update Count : 10 14 14 // 15 15 … … 91 91 this.lock = NULL; 92 92 } 93 static inline void ^?{}(FinishAction & ) {}93 static inline void ^?{}(FinishAction & this) {} 94 94 95 95 // Processor … … 176 176 __dllist_t(struct processor) procs; 177 177 __dllist_t(struct processor) idles; 178 unsigned int nprocessors; 179 180 // List of threads 178 179 // List of processors 181 180 __spinlock_t thread_list_lock; 182 181 __dllist_t(struct thread_desc) threads; 183 unsigned int nthreads;184 182 185 183 // Link lists fields … … 202 200 } 203 201 204 static inline struct processor * active_processor() { return TL_GET( this_processor ); } // UNSAFE205 static inline struct cluster * active_cluster () { return TL_GET( this_processor )->cltr; }206 207 202 // Local Variables: // 208 203 // mode: c // -
libcfa/src/concurrency/thread.hfa
rc1ea11b r18e683b 10 10 // Created On : Tue Jan 17 12:27:26 2017 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Fri Jun 21 17:51:33 201913 // Update Count : 512 // Last Modified On : Thu Mar 29 14:07:11 2018 13 // Update Count : 4 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 95 93 // Local Variables: // 96 94 // mode: c // -
src/ResolvExpr/Cost.h
rc1ea11b r18e683b 10 10 // Created On : Sun May 17 09:39:50 2015 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Fri Jun 21 11:39:13201913 // Update Count : 6312 // Last Modified On : Mon Apr 29 18:33:44 2019 13 // Update Count : 49 14 14 // 15 15 … … 21 21 22 22 namespace ResolvExpr { 23 #if 0 24 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 > other 55 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) conversions 70 int polyCost; ///< Count of parameters and return values bound to some poly type 71 int safeCost; ///< Safe (widening) conversions 72 int signCost; ///< Count of safe sign conversions 73 int varCost; ///< Count of polymorphic type variables 74 int specCost; ///< Polymorphic type specializations (type assertions), negative cost 75 int referenceCost; ///< reference conversions 76 }; 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 } // if 184 } 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.unsafeCost 201 && polyCost == other.polyCost 202 && safeCost == other.safeCost 203 && signCost == other.signCost 204 && varCost == other.varCost 205 && specCost == other.specCost 206 && 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 #else 221 222 //*************************** NEW *************************** 223 23 224 // To maximize performance and space, the 7 resolution costs are packed into a single 64-bit word. However, the 24 225 // specialization cost is a negative value so a correction is needed is a few places. … … 170 371 << ", " << cost.get_referenceCost() << " )"; 171 372 } 373 #endif // 0 172 374 } // namespace ResolvExpr 173 375 -
tests/concurrent/examples/boundedBufferTHREAD.cfa
rc1ea11b r18e683b 5 5 // file "LICENCE" distributed with Cforall. 6 6 // 7 // boundedBuffer THREAD.c --7 // boundedBufferEXT.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 11:50:12201913 // Update Count : 2 412 // Last Modified On : Fri Jun 21 08:15:58 2019 13 // Update Count : 23 14 14 // 15 15 -
tools/stat.py
rc1ea11b r18e683b 11 11 content = f.readlines() 12 12 content = [x.strip() for x in content] 13 content = [ float(x) for x in content] # expect floating-point strings14 content.remove(max(content)) # need at least 4 data values because15 content.remove(min(content)) # the max and min values are removed16 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 )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 ) 20 20 21 21
Note:
See TracChangeset
for help on using the changeset viewer.