- Timestamp:
- Aug 31, 2023, 11:31:15 PM (2 years ago)
- Branches:
- master
- Children:
- 950c58e
- Parents:
- 92355883 (diff), 686912c (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the(diff)links above to see all the changes relative to each parent. - Location:
- libcfa
- Files:
-
- 2 added
- 1 deleted
- 52 edited
- 17 moved
-
prelude/bootloader.cf (modified) (2 diffs)
-
prelude/builtins.c (modified) (4 diffs)
-
prelude/prelude-gen.cc (modified) (1 diff)
-
src/Exception.hfa (added)
-
src/Makefile.am (modified) (5 diffs)
-
src/bits/algorithm.hfa (modified) (8 diffs)
-
src/bits/collections.hfa (moved) (moved from libcfa/src/bits/containers.hfa ) (1 diff)
-
src/bits/debug.cfa (modified) (2 diffs)
-
src/bits/queue.hfa (modified) (1 diff)
-
src/bits/weakso_locks.cfa (modified) (1 diff)
-
src/bits/weakso_locks.hfa (modified) (3 diffs)
-
src/collections/array.hfa (moved) (moved from libcfa/src/containers/array.hfa ) (1 diff)
-
src/collections/list.hfa (moved) (moved from libcfa/src/containers/list.hfa )
-
src/collections/lockfree.hfa (moved) (moved from libcfa/src/containers/lockfree.hfa )
-
src/collections/maybe.cfa (moved) (moved from libcfa/src/containers/maybe.cfa ) (1 diff)
-
src/collections/maybe.hfa (moved) (moved from libcfa/src/containers/maybe.hfa )
-
src/collections/pair.cfa (moved) (moved from libcfa/src/containers/pair.cfa ) (1 diff)
-
src/collections/pair.hfa (moved) (moved from libcfa/src/containers/pair.hfa )
-
src/collections/result.cfa (moved) (moved from libcfa/src/containers/result.cfa ) (1 diff)
-
src/collections/result.hfa (moved) (moved from libcfa/src/containers/result.hfa )
-
src/collections/string.cfa (moved) (moved from libcfa/src/containers/string.cfa ) (13 diffs)
-
src/collections/string.hfa (added)
-
src/collections/string_res.cfa (moved) (moved from libcfa/src/containers/string_res.cfa ) (18 diffs)
-
src/collections/string_res.hfa (moved) (moved from libcfa/src/containers/string_res.hfa ) (3 diffs)
-
src/collections/string_sharectx.hfa (moved) (moved from libcfa/src/containers/string_sharectx.hfa )
-
src/collections/vector.cfa (moved) (moved from libcfa/src/containers/vector.cfa ) (1 diff)
-
src/collections/vector.hfa (moved) (moved from libcfa/src/containers/vector.hfa )
-
src/collections/vector2.hfa (moved) (moved from libcfa/src/containers/vector2.hfa )
-
src/common.hfa (modified) (4 diffs)
-
src/concurrency/actor.hfa (modified) (13 diffs)
-
src/concurrency/alarm.hfa (modified) (2 diffs)
-
src/concurrency/channel.hfa (modified) (10 diffs)
-
src/concurrency/coroutine.cfa (modified) (4 diffs)
-
src/concurrency/coroutine.hfa (modified) (2 diffs)
-
src/concurrency/future.hfa (modified) (2 diffs)
-
src/concurrency/invoke.h (modified) (5 diffs)
-
src/concurrency/iofwd.hfa (modified) (3 diffs)
-
src/concurrency/kernel.cfa (modified) (1 diff)
-
src/concurrency/kernel.hfa (modified) (2 diffs)
-
src/concurrency/kernel/startup.cfa (modified) (1 diff)
-
src/concurrency/locks.cfa (modified) (1 diff)
-
src/concurrency/locks.hfa (modified) (9 diffs)
-
src/concurrency/once.hfa (modified) (1 diff)
-
src/concurrency/select.cfa (modified) (1 diff)
-
src/concurrency/select.hfa (modified) (3 diffs)
-
src/concurrency/stats.cfa (modified) (1 diff)
-
src/containers/string.hfa (deleted)
-
src/exception.c (modified) (7 diffs)
-
src/exception.h (modified) (1 diff)
-
src/executor.baseline.txt (modified) (1 diff)
-
src/executor.cfa (modified) (1 diff)
-
src/fstream.cfa (modified) (6 diffs)
-
src/fstream.hfa (modified) (7 diffs)
-
src/gmp.hfa (modified) (2 diffs)
-
src/heap.cfa (modified) (10 diffs)
-
src/iostream.cfa (modified) (69 diffs)
-
src/iostream.hfa (modified) (17 diffs)
-
src/parseargs.cfa (modified) (1 diff)
-
src/parseconfig.cfa (modified) (5 diffs)
-
src/parseconfig.hfa (modified) (2 diffs)
-
src/rational.cfa (modified) (2 diffs)
-
src/rational.hfa (modified) (2 diffs)
-
src/stdlib.cfa (modified) (4 diffs)
-
src/stdlib.hfa (modified) (4 diffs)
-
src/strstream.cfa (modified) (5 diffs)
-
src/strstream.hfa (modified) (3 diffs)
-
src/time.cfa (modified) (3 diffs)
-
src/vec/vec.hfa (modified) (1 diff)
-
src/vec/vec2.hfa (modified) (1 diff)
-
src/vec/vec3.hfa (modified) (1 diff)
-
src/vec/vec4.hfa (modified) (1 diff)
-
src/virtual_dtor.hfa (modified) (2 diffs)
Legend:
- Unmodified
- Added
- Removed
-
libcfa/prelude/bootloader.cf
r92355883 r2a301ff 1 extern "C" { static inline int invoke_main( int argc, char* argv[], char* envp[]); }1 extern "C" { static inline int invoke_main( int argc, char * argv[], char * envp[]); } 2 2 int cfa_args_argc; 3 3 char ** cfa_args_argv; … … 5 5 __attribute__((weak)) extern int cfa_main_returned; 6 6 7 int main( int argc, char* argv[], char* envp[]) {7 int main( int argc, char * argv[], char * envp[] ) { 8 8 cfa_args_argc = argc; 9 9 cfa_args_argv = argv; 10 10 cfa_args_envp = envp; 11 11 int ret = invoke_main(argc, argv, envp); 12 if( &cfa_main_returned) cfa_main_returned = 1;12 if( &cfa_main_returned ) cfa_main_returned = 1; 13 13 return ret; 14 14 } -
libcfa/prelude/builtins.c
r92355883 r2a301ff 132 132 } // distribution 133 133 134 #define __CFA_BASE_COMP_1__() if ( x == 1 ) return 1135 #define __CFA_BASE_COMP_2__() if ( x == 2 ) return x << (y - 1)136 #define __CFA_EXP_OVERFLOW__() if ( y >= sizeof(y) * CHAR_BIT ) return 0137 138 134 #define __CFA_EXP__() \ 139 135 if ( y == 0 ) return 1; /* convention */ \ 140 __CFA_BASE_COMP_1__(); /* base case */ \ 141 __CFA_BASE_COMP_2__(); /* special case, positive shifting for integral types */ \ 142 __CFA_EXP_OVERFLOW__(); /* immediate overflow, negative exponent > 2^size-1 */ \ 136 __CFA_EXP_INT__( /* special cases for integral types */ \ 137 if ( x == 1 ) return 1; /* base case */ \ 138 if ( x == 2 ) return x << (y - 1); /* positive shifting */ \ 139 if ( y >= sizeof(y) * CHAR_BIT ) return 0; /* immediate overflow, negative exponent > 2^size-1 */ \ 140 ) \ 143 141 typeof(x) op = 1; /* accumulate odd product */ \ 144 142 for ( ; y > 1; y >>= 1 ) { /* squaring exponentiation, O(log2 y) */ \ … … 147 145 } \ 148 146 return x * op 147 #define __CFA_EXP_INT__(...) __VA_ARGS__ 149 148 150 149 static inline { … … 158 157 } // distribution 159 158 160 #undef __CFA_BASE_COMP_1__ 161 #undef __CFA_BASE_COMP_2__ 162 #undef __CFA_EXP_OVERFLOW__ 163 #define __CFA_BASE_COMP_1__() 164 #define __CFA_BASE_COMP_2__() 165 #define __CFA_EXP_OVERFLOW__() 159 #undef __CFA_EXP_INT__ 160 #define __CFA_EXP_INT__(...) 166 161 167 162 static inline forall( OT | { void ?{}( OT & this, one_t ); OT ?*?( OT, OT ); } ) { … … 171 166 } // distribution 172 167 173 #undef __CFA_BASE_COMP_1__ 174 #undef __CFA_BASE_COMP_2__ 175 #undef __CFA_EXP_OVERFLOW__ 168 #undef __CFA_EXP_INT__ 169 #undef __CFA_EXP__ 176 170 177 171 static inline { -
libcfa/prelude/prelude-gen.cc
r92355883 r2a301ff 159 159 int main() { 160 160 cout << "# 2 \"prelude.cfa\" // needed for error messages from this file" << endl; 161 cout << "forall( T &) trait sized {};" << endl;161 cout << "forall( T * ) trait sized {};" << endl; 162 162 163 163 cout << "//////////////////////////" << endl; -
libcfa/src/Makefile.am
r92355883 r2a301ff 11 11 ## Created On : Sun May 31 08:54:01 2015 12 12 ## Last Modified By : Peter A. Buhr 13 ## Last Modified On : Thu May 25 15:20:04202314 ## Update Count : 2 5913 ## Last Modified On : Wed Aug 30 21:22:45 2023 14 ## Update Count : 263 15 15 ############################################################################### 16 16 … … 40 40 if BUILDLIB 41 41 inst_headers_nosrc = \ 42 Exception.hfa \ 42 43 bitmanip.hfa \ 43 44 clock.hfa \ … … 51 52 bits/algorithm.hfa \ 52 53 bits/align.hfa \ 53 bits/co ntainers.hfa \54 bits/collections.hfa \ 54 55 bits/debug.hfa \ 55 56 bits/defs.hfa \ … … 62 63 concurrency/iofwd.hfa \ 63 64 concurrency/barrier.hfa \ 64 co ntainers/array.hfa \65 co ntainers/list.hfa \66 co ntainers/lockfree.hfa \67 co ntainers/string_sharectx.hfa \68 co ntainers/vector2.hfa \65 collections/array.hfa \ 66 collections/list.hfa \ 67 collections/lockfree.hfa \ 68 collections/string_sharectx.hfa \ 69 collections/vector2.hfa \ 69 70 vec/vec.hfa \ 70 71 vec/vec2.hfa \ … … 88 89 bits/weakso_locks.hfa \ 89 90 algorithms/range_iterator.hfa \ 90 co ntainers/maybe.hfa \91 co ntainers/pair.hfa \92 co ntainers/result.hfa \93 co ntainers/string.hfa \94 co ntainers/string_res.hfa \95 co ntainers/vector.hfa \91 collections/maybe.hfa \ 92 collections/pair.hfa \ 93 collections/result.hfa \ 94 collections/string.hfa \ 95 collections/string_res.hfa \ 96 collections/vector.hfa \ 96 97 device/cpu.hfa 97 98 -
libcfa/src/bits/algorithm.hfa
r92355883 r2a301ff 9 9 // Author : Thierry Delisle 10 10 // Created On : Mon Oct 30 13:37:34 2017 11 // Last Modified By : --12 // Last Modified On : --13 // Update Count : 011 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Sat Jul 22 08:25:29 2023 13 // Update Count : 3 14 14 // 15 15 … … 17 17 18 18 #ifdef SAFE_SORT 19 forall( T | { int ?<?( T, T ); int ?>?( T, T ); } ) static inline void __libcfa_small_sort2( T * arr );20 forall( T | { int ?<?( T, T ); int ?>?( T, T ); } ) static inline void __libcfa_small_sort3( T * arr );21 forall( T | { int ?<?( T, T ); int ?>?( T, T ); } ) static inline void __libcfa_small_sort4( T * arr );22 forall( T | { int ?<?( T, T ); int ?>?( T, T ); } ) static inline void __libcfa_small_sort5( T * arr );23 forall( T | { int ?<?( T, T ); int ?>?( T, T ); } ) static inline void __libcfa_small_sort6( T * arr );24 forall( T | { int ?<?( T, T ); int ?>?( T, T ); } ) static inline void __libcfa_small_sortN( T * arr, size_t dim );19 forall( T | { int ?<?( T, T ); int ?>?( T, T ); } ) static inline void __libcfa_small_sort2( T * arr ); 20 forall( T | { int ?<?( T, T ); int ?>?( T, T ); } ) static inline void __libcfa_small_sort3( T * arr ); 21 forall( T | { int ?<?( T, T ); int ?>?( T, T ); } ) static inline void __libcfa_small_sort4( T * arr ); 22 forall( T | { int ?<?( T, T ); int ?>?( T, T ); } ) static inline void __libcfa_small_sort5( T * arr ); 23 forall( T | { int ?<?( T, T ); int ?>?( T, T ); } ) static inline void __libcfa_small_sort6( T * arr ); 24 forall( T | { int ?<?( T, T ); int ?>?( T, T ); } ) static inline void __libcfa_small_sortN( T * arr, size_t dim ); 25 25 26 forall( T | { int ?<?( T, T ); int ?>?( T, T ); } )26 forall( T | { int ?<?( T, T ); int ?>?( T, T ); } ) 27 27 static inline void __libcfa_small_sort( T * arr, size_t dim ) { 28 28 switch( dim ) { … … 41 41 #define SWAP(x,y) { T a = min(arr[x], arr[y]); T b = max(arr[x], arr[y]); arr[x] = a; arr[y] = b;} 42 42 43 forall( T | { int ?<?( T, T ); int ?>?( T, T ); } )43 forall( T | { int ?<?( T, T ); int ?>?( T, T ); } ) 44 44 static inline void __libcfa_small_sort2( T * arr ) { 45 45 SWAP(0, 1); 46 46 } 47 47 48 forall( T | { int ?<?( T, T ); int ?>?( T, T ); } )48 forall( T | { int ?<?( T, T ); int ?>?( T, T ); } ) 49 49 static inline void __libcfa_small_sort3( T * arr ) { 50 50 SWAP(1, 2); … … 53 53 } 54 54 55 forall( T | { int ?<?( T, T ); int ?>?( T, T ); } )55 forall( T | { int ?<?( T, T ); int ?>?( T, T ); } ) 56 56 static inline void __libcfa_small_sort4( T * arr ) { 57 57 SWAP(0, 1); … … 62 62 } 63 63 64 forall( T | { int ?<?( T, T ); int ?>?( T, T ); } )64 forall( T | { int ?<?( T, T ); int ?>?( T, T ); } ) 65 65 static inline void __libcfa_small_sort5( T * arr ) { 66 66 SWAP(0, 1); … … 75 75 } 76 76 77 forall( T | { int ?<?( T, T ); int ?>?( T, T ); } )77 forall( T | { int ?<?( T, T ); int ?>?( T, T ); } ) 78 78 static inline void __libcfa_small_sort6( T * arr ) { 79 79 SWAP(1, 2); … … 91 91 } 92 92 93 forall( T | { int ?<?( T, T ); int ?>?( T, T ); } )93 forall( T | { int ?<?( T, T ); int ?>?( T, T ); } ) 94 94 static inline void __libcfa_small_sortN( T * arr, size_t dim ) { 95 int i, j; 96 for (i = 1; i < dim; i++) { 95 for ( i; 1 ~ dim ) { 97 96 T tmp = arr[i]; 98 for (j = i; j >= 1 && tmp < arr[j-1]; j--) { 97 int j; 98 for ( j = i; j >= 1 && tmp < arr[j-1]; j--) { 99 99 arr[j] = arr[j-1]; 100 100 } … … 175 175 176 176 static inline void __libcfa_small_sortN( void* * arr, size_t dim ) { 177 int i, j;178 for (i = 1; i < dim; i++) {179 void* tmp = arr[i];177 for ( i; 1 ~ dim ) { 178 void * tmp = arr[i]; 179 int j; 180 180 for (j = i; j >= 1 && tmp < arr[j-1]; j--) { 181 181 arr[j] = arr[j-1]; -
libcfa/src/bits/collections.hfa
r92355883 r2a301ff 5 5 // file "LICENCE" distributed with Cforall. 6 6 // 7 // bits/co ntainers.hfa -- Intrusive generic containers.hfa7 // bits/collections.hfa -- Intrusive generic collections 8 8 // 9 9 // Author : Thierry Delisle 10 10 // Created On : Tue Oct 31 16:38:50 2017 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Thu Feb 2 11:33:08202313 // Update Count : 2912 // Last Modified On : Wed Aug 30 21:26:39 2023 13 // Update Count : 30 14 14 15 15 #pragma once -
libcfa/src/bits/debug.cfa
r92355883 r2a301ff 10 10 // Created On : Thu Mar 30 12:30:01 2017 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Fri Apr 22 18:20:26 202213 // Update Count : 1 312 // Last Modified On : Sat Jul 22 08:17:27 2023 13 // Update Count : 14 14 14 // 15 15 … … 33 33 in_buffer += count; 34 34 35 for ( ;;) {35 for () { 36 36 retcode = write( fd, in_buffer, len - count ); 37 37 -
libcfa/src/bits/queue.hfa
r92355883 r2a301ff 91 91 T * prev = 0p; 92 92 T * curr = (T *)root; 93 for ( ;;) {93 for () { 94 94 if ( &n == curr ) { // found => remove 95 95 if ( (T *)root == &n ) { -
libcfa/src/bits/weakso_locks.cfa
r92355883 r2a301ff 30 30 bool register_select( blocking_lock & this, select_node & node ) { return false; } 31 31 bool unregister_select( blocking_lock & this, select_node & node ) { return false; } 32 void on_selected( blocking_lock & this, select_node & node ) {}32 bool on_selected( blocking_lock & this, select_node & node ) { return true; } 33 33 -
libcfa/src/bits/weakso_locks.hfa
r92355883 r2a301ff 20 20 #include "bits/locks.hfa" 21 21 #include "bits/sequence.hfa" 22 #include "bits/co ntainers.hfa"23 #include "co ntainers/list.hfa"22 #include "bits/collections.hfa" 23 #include "collections/list.hfa" 24 24 25 25 struct select_node; … … 62 62 bool register_select( blocking_lock & this, select_node & node ) OPTIONAL_THREAD; 63 63 bool unregister_select( blocking_lock & this, select_node & node ) OPTIONAL_THREAD; 64 void on_selected( blocking_lock & this, select_node & node ) OPTIONAL_THREAD; 64 bool on_selected( blocking_lock & this, select_node & node ) OPTIONAL_THREAD; 65 blocking_lock __CFA_select_get_type( blocking_lock this ) OPTIONAL_THREAD; 65 66 66 67 //---------- … … 80 81 static inline bool register_select( multiple_acquisition_lock & this, select_node & node ) { return register_select( (blocking_lock &)this, node ); } 81 82 static inline bool unregister_select( multiple_acquisition_lock & this, select_node & node ) { return unregister_select( (blocking_lock &)this, node ); } 82 static inline void on_selected( multiple_acquisition_lock & this, select_node & node ) { on_selected( (blocking_lock &)this, node ); } 83 static inline bool on_selected( multiple_acquisition_lock & this, select_node & node ) { return on_selected( (blocking_lock &)this, node ); } 84 multiple_acquisition_lock __CFA_select_get_type( multiple_acquisition_lock this ); -
libcfa/src/collections/array.hfa
r92355883 r2a301ff 247 247 248 248 // desired: 249 // trait ar(A &, Tv &, [N]) { 249 // forall(A &, Tv &, [N]) 250 // trait ar { 250 251 // Tv& ?[?]( A&, zero_t ); 251 252 // Tv& ?[?]( A&, one_t ); -
libcfa/src/collections/maybe.cfa
r92355883 r2a301ff 10 10 // Created On : Wed May 24 15:40:00 2017 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Sun Feb 17 11:22:03 201913 // Update Count : 312 // Last Modified On : Wed Aug 30 21:26:55 2023 13 // Update Count : 4 14 14 // 15 15 16 #include <co ntainers/maybe.hfa>16 #include <collections/maybe.hfa> 17 17 #include <assert.h> 18 18 -
libcfa/src/collections/pair.cfa
r92355883 r2a301ff 6 6 // Author : Aaron Moss 7 7 // Created On : Wed Apr 12 15:32:00 2017 8 // Last Modified By : Aaron Moss9 // Last Modified On : Wed A pr 12 15:32:00 201710 // Update Count : 18 // Last Modified By : Peter A. Buhr 9 // Last Modified On : Wed Aug 30 21:27:12 2023 10 // Update Count : 2 11 11 // 12 12 13 #include <co ntainers/pair.hfa>13 #include <collections/pair.hfa> 14 14 15 15 forall(R, S -
libcfa/src/collections/result.cfa
r92355883 r2a301ff 10 10 // Created On : Wed May 24 15:40:00 2017 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Sun Feb 17 11:24:04 201913 // Update Count : 312 // Last Modified On : Wed Aug 30 21:27:22 2023 13 // Update Count : 4 14 14 // 15 15 16 #include <co ntainers/result.hfa>16 #include <collections/result.hfa> 17 17 #include <assert.h> 18 18 -
libcfa/src/collections/string.cfa
r92355883 r2a301ff 9 9 // Author : Michael L. Brooks 10 10 // Created On : Fri Sep 03 11:00:00 2021 11 // Last Modified By : Michael L. Brooks12 // Last Modified On : Fri Sep 03 11:00:00 202113 // Update Count : 1 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Thu Aug 31 13:20:41 2023 13 // Update Count : 161 14 14 // 15 15 … … 55 55 } 56 56 57 void ?{}( string & this, const char * buffer, size_t bsize) {57 void ?{}( string & this, const char * buffer, size_t bsize) { 58 58 (this.inner) { malloc() }; 59 59 ?{}( *this.inner, buffer, bsize ); … … 100 100 101 101 //////////////////////////////////////////////////////// 102 // Output 103 104 ofstream & ?|?( ofstream & fs, const string & this ) { 105 return fs | (*this.inner); 106 } 107 108 void ?|?( ofstream & fs, const string & this ) { 109 fs | (*this.inner); 102 // Input-Output 103 104 ofstream & ?|?( ofstream & out, const string & this ) { 105 return out | (*this.inner); // print internal string_res 106 } 107 108 void ?|?( ofstream & out, const string & this ) { 109 (ofstream &)(out | (*this.inner)); ends( out ); 110 } 111 112 ifstream & ?|?(ifstream & in, string & this) { 113 return in | (*this.inner); // read to internal string_res 114 } 115 116 void ?|?( ifstream & in, string & this ) { 117 (ifstream &)(in | this); ends( in ); 118 } 119 120 ifstream & ?|?( ifstream & is, _Istream_str f ) { 121 // skip, same as for char * 122 if ( ! &f.s ) { 123 // fprintf( stderr, "skip %s %d\n", f.scanset, f.wd ); 124 if ( f.wd == -1 ) fmt( is, f.scanset, "" ); // no input arguments 125 else for ( f.wd ) fmt( is, "%*c" ); 126 return is; 127 } // if 128 129 // .---------------, 130 // | | | | |...|0|0| check and guard 131 // `---------------' 132 enum { gwd = 128 + 2, wd = gwd - 1 }; // guarded and unguarded width 133 char cstr[gwd]; // read in chunks 134 bool cont = false; 135 136 if ( f.wd == -1 ) f.wd = wd; 137 _Istream_Cstr cfmt = { cstr, (_Istream_str_base)f }; 138 139 cstr[wd] = '\0'; // guard null terminate string 140 try { 141 is | cfmt; 142 } catch( cstring_length * ) { 143 cont = true; 144 } finally { 145 f.s = cstr; // ok to initialize string 146 } // try 147 for ( ; cont; ) { // overflow read ? 148 cont = false; 149 try { 150 is | cfmt; 151 } catch( cstring_length * ) { 152 cont = true; // continue not allowed 153 } finally { 154 f.s += cstr; // build string chunk at a time 155 } // try 156 } // for 157 return is; 158 } // ?|? 159 160 void ?|?( ifstream & in, _Istream_str f ) { 161 (ifstream &)(in | f); ends( in ); 110 162 } 111 163 … … 118 170 } 119 171 172 string ?()( string & this, size_t start ) { 173 string ret = { *this.inner, start, size( this ) }; 174 return ret`shareEdits; 175 } 176 120 177 //////////////////////////////////////////////////////// 121 178 // Comparison 122 179 123 bool ?==?(const string & s, const string &other) {180 bool ?==?(const string & s, const string & other) { 124 181 return *s.inner == *other.inner; 125 182 } 126 183 127 bool ?!=?(const string & s, const string &other) {184 bool ?!=?(const string & s, const string & other) { 128 185 return *s.inner != *other.inner; 129 186 } 130 187 131 bool ?==?(const string & s, const char* other) {188 bool ?==?(const string & s, const char * other) { 132 189 return *s.inner == other; 133 190 } 134 191 135 bool ?!=?(const string & s, const char* other) {192 bool ?!=?(const string & s, const char * other) { 136 193 return *s.inner != other; 137 194 } … … 140 197 // Getter 141 198 142 size_t size(const string & s) {199 size_t size(const string & s) { 143 200 return size( * s.inner ); 144 201 } … … 147 204 // Concatenation 148 205 149 void ?+=?(string & s, char other) {206 void ?+=?(string & s, char other) { 150 207 (*s.inner) += other; 151 208 } 152 209 153 void ?+=?(string & s, const string &s2) {210 void ?+=?(string & s, const string & s2) { 154 211 (*s.inner) += (*s2.inner); 155 212 } 156 213 157 void ?+=?(string & s, const char* other) {214 void ?+=?(string & s, const char * other) { 158 215 (*s.inner) += other; 159 216 } 160 217 161 string ?+?(const string & s, char other) {218 string ?+?(const string & s, char other) { 162 219 string ret = s; 163 220 ret += other; … … 165 222 } 166 223 167 string ?+?(const string & s, const string &s2) {224 string ?+?(const string & s, const string & s2) { 168 225 string ret = s; 169 226 ret += s2; … … 171 228 } 172 229 173 string ?+?(const char * s1, const char* s2) {230 string ?+?(const char * s1, const char * s2) { 174 231 string ret = s1; 175 232 ret += s2; … … 177 234 } 178 235 179 string ?+?(const string & s, const char* other) {236 string ?+?(const string & s, const char * other) { 180 237 string ret = s; 181 238 ret += other; … … 186 243 // Repetition 187 244 188 string ?*?(const string & s, size_t factor) {245 string ?*?(const string & s, size_t factor) { 189 246 string ret = ""; 190 247 for (factor) ret += s; … … 206 263 // Character access 207 264 208 char ?[?](const string & s, size_t index) {265 char ?[?](const string & s, size_t index) { 209 266 return (*s.inner)[index]; 210 267 } 211 268 212 string ?[?](string & s, size_t index) {269 string ?[?](string & s, size_t index) { 213 270 string ret = { *s.inner, index, index + 1 }; 214 271 return ret`shareEdits; … … 218 275 // Search 219 276 220 bool contains(const string & s, char ch) {277 bool contains(const string & s, char ch) { 221 278 return contains( *s.inner, ch ); 222 279 } 223 280 224 int find(const string & s, char search) {281 int find(const string & s, char search) { 225 282 return find( *s.inner, search ); 226 283 } 227 284 228 int find(const string & s, const string &search) {285 int find(const string & s, const string & search) { 229 286 return find( *s.inner, *search.inner ); 230 287 } 231 288 232 int find(const string & s, const char* search) {289 int find(const string & s, const char * search) { 233 290 return find( *s.inner, search); 234 291 } 235 292 236 int find(const string & s, const char* search, size_t searchsize) {293 int find(const string & s, const char * search, size_t searchsize) { 237 294 return find( *s.inner, search, searchsize); 238 295 } 239 296 240 int findFrom(const string & s, size_t fromPos, char search) {297 int findFrom(const string & s, size_t fromPos, char search) { 241 298 return findFrom( *s.inner, fromPos, search ); 242 299 } 243 300 244 int findFrom(const string & s, size_t fromPos, const string &search) {301 int findFrom(const string & s, size_t fromPos, const string & search) { 245 302 return findFrom( *s.inner, fromPos, *search.inner ); 246 303 } 247 304 248 int findFrom(const string & s, size_t fromPos, const char* search) {305 int findFrom(const string & s, size_t fromPos, const char * search) { 249 306 return findFrom( *s.inner, fromPos, search ); 250 307 } 251 308 252 int findFrom(const string & s, size_t fromPos, const char* search, size_t searchsize) {309 int findFrom(const string & s, size_t fromPos, const char * search, size_t searchsize) { 253 310 return findFrom( *s.inner, fromPos, search, searchsize ); 254 311 } 255 312 256 bool includes(const string & s, const string &search) {313 bool includes(const string & s, const string & search) { 257 314 return includes( *s.inner, *search.inner ); 258 315 } 259 316 260 bool includes(const string & s, const char* search) {317 bool includes(const string & s, const char * search) { 261 318 return includes( *s.inner, search ); 262 319 } 263 320 264 bool includes(const string & s, const char* search, size_t searchsize) {321 bool includes(const string & s, const char * search, size_t searchsize) { 265 322 return includes( *s.inner, search, searchsize ); 266 323 } 267 324 268 bool startsWith(const string & s, const string &prefix) {325 bool startsWith(const string & s, const string & prefix) { 269 326 return startsWith( *s.inner, *prefix.inner ); 270 327 } 271 328 272 bool startsWith(const string & s, const char* prefix) {329 bool startsWith(const string & s, const char * prefix) { 273 330 return startsWith( *s.inner, prefix ); 274 331 } 275 332 276 bool startsWith(const string & s, const char* prefix, size_t prefixsize) {333 bool startsWith(const string & s, const char * prefix, size_t prefixsize) { 277 334 return startsWith( *s.inner, prefix, prefixsize ); 278 335 } 279 336 280 bool endsWith(const string & s, const string &suffix) {337 bool endsWith(const string & s, const string & suffix) { 281 338 return endsWith( *s.inner, *suffix.inner ); 282 339 } 283 340 284 bool endsWith(const string & s, const char* suffix) {341 bool endsWith(const string & s, const char * suffix) { 285 342 return endsWith( *s.inner, suffix ); 286 343 } 287 344 288 bool endsWith(const string & s, const char* suffix, size_t suffixsize) {345 bool endsWith(const string & s, const char * suffix, size_t suffixsize) { 289 346 return endsWith( *s.inner, suffix, suffixsize ); 290 347 } … … 316 373 317 374 318 int exclude(const string & s, const charclass &mask) {375 int exclude(const string & s, const charclass & mask) { 319 376 return exclude( *s.inner, *mask.inner ); 320 377 } 321 378 /* 322 StrSlice exclude(string & s, const charclass &mask) {379 StrSlice exclude(string & s, const charclass & mask) { 323 380 } 324 381 */ 325 382 326 int include(const string & s, const charclass &mask) {383 int include(const string & s, const charclass & mask) { 327 384 return include( *s.inner, *mask.inner ); 328 385 } 329 386 330 387 /* 331 StrSlice include(string & s, const charclass &mask) {388 StrSlice include(string & s, const charclass & mask) { 332 389 } 333 390 */ -
libcfa/src/collections/string_res.cfa
r92355883 r2a301ff 9 9 // Author : Michael L. Brooks 10 10 // Created On : Fri Sep 03 11:00:00 2021 11 // Last Modified By : Michael L. Brooks12 // Last Modified On : Fri Sep 03 11:00:00 202113 // Update Count : 1 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Mon Aug 14 18:06:01 2023 13 // Update Count : 12 14 14 // 15 15 … … 17 17 #include "string_sharectx.hfa" 18 18 #include "stdlib.hfa" 19 #include <ctype.h> 19 20 20 21 // Workaround for observed performance penalty from calling CFA's alloc. … … 134 135 serr | nlOff; 135 136 serr | " lnth:" | lnth | " s:" | (void *)s | ",\""; 136 for ( i nt i = 0; i < lnth; i += 1) {137 for ( i; lnth ) { 137 138 serr | s[i]; 138 139 } // for … … 198 199 // Output operator 199 200 ofstream & ?|?(ofstream &out, const string_res &s) { 200 // Store auto-newline state so it can be restored 201 bool anl = getANL$(out); 202 nlOff(out); 203 for (size_t i = 0; i < s.Handle.lnth; i++) { 204 out | s[i]; 205 } 206 out | sep; 207 // Re-apply newlines after done, for chaining version 208 if (anl) nlOn(out); 201 // CFA string is NOT null terminated, so print exactly lnth characters in a minimum width of 0. 202 out | wd( 0, s.Handle.lnth, s.Handle.s ) | nonl; 209 203 return out; 210 204 } 211 205 212 206 void ?|?(ofstream &out, const string_res &s) { 213 // Store auto-newline state so it can be restored 214 bool anl = getANL$(out); 215 if( s.Handle.lnth == 0 ) { 216 sout | ""; 217 } else { 218 nlOff(out); 219 for (size_t i = 0; i < s.Handle.lnth; i++) { 220 // Need to re-apply on the last output operator, for whole-statement version 221 if (anl && i == s.Handle.lnth-1) nlOn(out); 222 out | s[i]; 223 } 224 } 225 } 207 (ofstream &)(out | s); ends( out ); 208 } 209 210 // Input operator 211 ifstream & ?|?(ifstream &in, string_res &s) { 212 213 // Reading into a temp before assigning to s is near zero overhead in typical cases because of sharing. 214 // If s is a substring of something larger, simple assignment takes care of that case correctly. 215 // But directly reading a variable amount of text into the middle of a larger context is not practical. 216 string_res temp; 217 218 // Read in chunks. Often, one chunk is enough. Keep the string that accumulates chunks last in the heap, 219 // so available room is rest of heap. When a chunk fills the heap, force growth then take the next chunk. 220 for (;;) { 221 // Append dummy content to temp, forcing expansion when applicable (occurs always on subsequent loops) 222 // length 2 ensures room for at least one real char, plus scanf/pipe-cstr's null terminator 223 temp += "--"; 224 assert( temp.Handle.ulink->EndVbyte == temp.Handle.s + temp.Handle.lnth ); // last in heap 225 226 // reset, to overwrite the appended "--" 227 temp.Handle.lnth -= 2; 228 temp.Handle.ulink->EndVbyte -= 2; 229 230 // rest of heap, less 1 byte for null terminator, is available to read into 231 int lenReadable = (char*)temp.Handle.ulink->ExtVbyte - temp.Handle.ulink->EndVbyte - 1; 232 assert (lenReadable >= 1); 233 234 // get bytes 235 in | wdi( lenReadable + 1, lenReadable, temp.Handle.ulink->EndVbyte ); 236 int lenWasRead = strlen(temp.Handle.ulink->EndVbyte); 237 238 // update metadata 239 temp.Handle.lnth += lenWasRead; 240 temp.Handle.ulink->EndVbyte += lenWasRead; 241 242 if (lenWasRead < lenReadable) break; 243 } 244 245 s = temp; 246 return in; 247 } 248 226 249 227 250 // Empty constructor … … 338 361 // adjust all substring string and handle locations, and check if any substring strings are outside the new base string 339 362 char *limit = resultSesStart + resultSesLnth; 340 for ( string_res * p = this.shareEditSet_next; p != &this; p = p->shareEditSet_next) {363 for ( string_res * p = this.shareEditSet_next; p != &this; p = p->shareEditSet_next ) { 341 364 verify (p->Handle.s >= beforeBegin); 342 365 if ( p->Handle.s >= afterBegin ) { … … 391 414 } 392 415 393 static string_res & assign_(string_res &this, const char* buffer, size_t bsize, const string_res & valSrc) { 394 395 // traverse the incumbent share-edit set (SES) to recover the range of a base string to which `this` belongs 396 string_res * shareEditSetStartPeer = & this; 397 string_res * shareEditSetEndPeer = & this; 416 // traverse the share-edit set (SES) to recover the range of a base string to which `this` belongs 417 static void locateInShareEditSet( string_res &this, string_res *&shareEditSetStartPeer, string_res *&shareEditSetEndPeer ) { 418 shareEditSetStartPeer = & this; 419 shareEditSetEndPeer = & this; 398 420 for (string_res * editPeer = this.shareEditSet_next; editPeer != &this; editPeer = editPeer->shareEditSet_next) { 399 421 if ( editPeer->Handle.s < shareEditSetStartPeer->Handle.s ) { … … 404 426 } 405 427 } 428 } 429 430 static string_res & assign_(string_res &this, const char* buffer, size_t bsize, const string_res & valSrc) { 431 432 string_res * shareEditSetStartPeer; 433 string_res * shareEditSetEndPeer; 434 locateInShareEditSet( this, shareEditSetStartPeer, shareEditSetEndPeer ); 406 435 407 436 verify( shareEditSetEndPeer->Handle.s >= shareEditSetStartPeer->Handle.s ); … … 589 618 590 619 bool contains(const string_res &s, char ch) { 591 for ( i; size(s)) {620 for ( i; size(s) ) { 592 621 if (s[i] == ch) return true; 593 622 } … … 643 672 } 644 673 645 for ( size_t i = fromPos; i < s.Handle.lnth; i++) {674 for ( i; fromPos ~ s.Handle.lnth ) { 646 675 size_t remaining = s.Handle.lnth - i; 647 676 // Never going to find the search string if the remaining string is … … 652 681 653 682 bool matched = true; 654 for ( size_t j = 0; j < searchsize; j++) {683 for ( j; searchsize ) { 655 684 if (search[j] != s.Handle.s[i + j]) { 656 685 matched = false; … … 740 769 741 770 int exclude(const string_res &s, const charclass_res &mask) { 742 for ( int i = 0; i < size(s); i++) {771 for ( i; size(s) ) { 743 772 if ( test(mask, s[i]) ) return i; 744 773 } … … 747 776 748 777 int include(const string_res &s, const charclass_res &mask) { 749 for ( int i = 0; i < size(s); i++) {778 for ( i; size(s) ) { 750 779 if ( ! test(mask, s[i]) ) return i; 751 780 } … … 775 804 for ( HandleNode *ni = HeaderPtr->flink; ni != HeaderPtr; ni = ni->flink ) { 776 805 serr | "\tnode:" | ni | " lnth:" | ni->lnth | " s:" | (void *)ni->s | ",\""; 777 for ( i nt i = 0; i < ni->lnth; i += 1) {806 for ( i; ni->lnth ) { 778 807 serr | ni->s[i]; 779 808 } // for … … 881 910 for ( HandleNode *n = HeaderPtr->flink; n != HeaderPtr; n = n->flink ) { 882 911 serr | "\tnode:" | n | " lnth:" | n->lnth | " s:" | (void *)n->s | ",\""; 883 for ( i nt i = 0; i < n->lnth; i += 1) {884 serr | n->s[i];912 for ( i; n->lnth ) { 913 serr | n->s[i]; 885 914 } // for 886 915 serr | "\" flink:" | n->flink | " blink:" | n->blink | nl; … … 960 989 EndVbyte = StartVbyte; 961 990 h = Header.flink; // ignore header node 962 for ( ;;) {991 for () { 963 992 memmove( EndVbyte, h->s, h->lnth ); 964 993 obase = h->s; … … 971 1000 // check if any substrings are allocated within a string 972 1001 973 for ( ;;) {1002 for () { 974 1003 if ( h == &Header ) break; // end of header list ? 975 1004 if ( h->s >= limit ) break; // outside of current string ? … … 1001 1030 serr | nlOff; 1002 1031 serr | "\tnode:" | n | " lnth:" | n->lnth | " s:" | (void *)n->s | ",\""; 1003 for ( i nt i = 0; i < n->lnth; i += 1) {1032 for ( i; n->lnth ) { 1004 1033 serr | n->s[i]; 1005 1034 } // for … … 1036 1065 serr | nlOff; 1037 1066 serr | "\tnode:" | n | " lnth:" | n->lnth | " s:" | (void *)n->s | ",\""; 1038 for ( i nt i = 0; i < n->lnth; i += 1) {1067 for ( i; n->lnth ) { 1039 1068 serr | n->s[i]; 1040 1069 } // for -
libcfa/src/collections/string_res.hfa
r92355883 r2a301ff 9 9 // Author : Michael L. Brooks 10 10 // Created On : Fri Sep 03 11:00:00 2021 11 // Last Modified By : Michael L. Brooks12 // Last Modified On : Fri Sep 03 11:00:00 202113 // Update Count : 111 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Sat Aug 12 15:45:47 2023 13 // Update Count : 2 14 14 // 15 15 … … 30 30 VbyteHeap *ulink; // upward link 31 31 32 char *s; // pointer to byte string32 char *s; // pointer to byte string 33 33 unsigned int lnth; // length of byte string 34 34 }; // HandleNode … … 101 101 ofstream & ?|?(ofstream &out, const string_res &s); 102 102 void ?|?(ofstream &out, const string_res &s); 103 ifstream & ?|?(ifstream &in, string_res &s); 103 104 104 105 // Concatenation -
libcfa/src/collections/vector.cfa
r92355883 r2a301ff 10 10 // Created On : Tue Jul 5 18:07:52 2016 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Tue Jul 5 18:08:31 201613 // Update Count : 212 // Last Modified On : Wed Aug 30 21:27:31 2023 13 // Update Count : 3 14 14 // 15 15 16 #include <co ntainers/vector.hfa>16 #include <collections/vector.hfa> 17 17 18 18 #include <stdlib.hfa> -
libcfa/src/common.hfa
r92355883 r2a301ff 10 10 // Created On : Wed Jul 11 17:54:36 2018 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Sat Oct 8 08:32:57 202213 // Update Count : 2312 // Last Modified On : Mon Aug 14 17:01:47 2023 13 // Update Count : 38 14 14 // 15 15 … … 66 66 67 67 static inline __attribute__((always_inline)) { 68 char min( char v1, char v2 ) { return v1 < v2 ? v1 : v2; } // optimization 68 forall( T | { int ?<?( T, T ); } ) 69 T min( T v1, T v2 ) { return v1 < v2 ? v1 : v2; } 70 71 forall( T, Ts... | { T min( T, T ); T min( T, Ts ); } ) 72 T min( T v1, T v2, Ts vs ) { return min( min( v1, v2 ), vs ); } 73 74 forall( T | { int ?>?( T, T ); } ) 75 T max( T v1, T v2 ) { return v1 > v2 ? v1 : v2; } 76 77 forall( T, Ts... | { T max( T, T ); T max( T, Ts ); } ) 78 T max( T v1, T v2, Ts vs ) { return max( max( v1, v2 ), vs ); } 79 80 forall( T | { T min( T, T ); T max( T, T ); } ) 81 T clamp( T value, T min_val, T max_val ) { return max( min_val, min( value, max_val ) ); } 82 83 forall( T ) 84 void swap( T & v1, T & v2 ) { T temp = v1; v1 = v2; v2 = temp; } 85 86 // Specializations 87 char min( char v1, char v2 ) { return v1 < v2 ? v1 : v2; } 69 88 int min( int v1, int v2 ) { return v1 < v2 ? v1 : v2; } 70 89 unsigned int min( unsigned int v1, unsigned int v2 ) { return v1 < v2 ? v1 : v2; } … … 73 92 long long int min( long long int v1, long long int v2 ) { return v1 < v2 ? v1 : v2; } 74 93 unsigned long long int min( unsigned long long int v1, unsigned long long int v2 ) { return v1 < v2 ? v1 : v2; } 75 forall( T | { int ?<?( T, T ); } ) // generic76 T min( T v1, T v2 ) { return v1 < v2 ? v1 : v2; }77 94 78 char max( char v1, char v2 ) { return v1 > v2 ? v1 : v2; } // optimization95 char max( char v1, char v2 ) { return v1 > v2 ? v1 : v2; } 79 96 int max( int v1, int v2 ) { return v1 > v2 ? v1 : v2; } 80 97 unsigned int max( unsigned int v1, unsigned int v2 ) { return v1 > v2 ? v1 : v2; } … … 83 100 long long int max( long long int v1, long long int v2 ) { return v1 > v2 ? v1 : v2; } 84 101 unsigned long long int max( unsigned long long int v1, unsigned long long int v2 ) { return v1 > v2 ? v1 : v2; } 85 forall( T | { int ?>?( T, T ); } ) // generic86 T max( T v1, T v2 ) { return v1 > v2 ? v1 : v2; }87 88 forall( T | { T min( T, T ); T max( T, T ); } )89 T clamp( T value, T min_val, T max_val ) { return max( min_val, min( value, max_val ) ); }90 91 forall( T )92 void swap( T & v1, T & v2 ) { T temp = v1; v1 = v2; v2 = temp; }93 102 } // distribution 94 103 -
libcfa/src/concurrency/actor.hfa
r92355883 r2a301ff 39 39 // #define ACTOR_STATS 40 40 41 // used to run and only track missed queue gulps 42 #ifdef ACTOR_STATS 43 #define ACTOR_STATS_QUEUE_MISSED 44 #endif 45 41 46 // forward decls 42 47 struct actor; … … 48 53 typedef allocation (*__receive_fn)(actor &, message &, actor **, message **); 49 54 struct request { 50 actor * receiver;51 message * msg;52 __receive_fn fn;55 actor * receiver; 56 message * msg; 57 __receive_fn fn; 53 58 }; 54 59 55 60 struct a_msg { 56 int m;61 int m; 57 62 }; 58 63 static inline void ?{}( request & this ) {} 59 64 static inline void ?{}( request & this, actor * receiver, message * msg, __receive_fn fn ) { 60 this.receiver = receiver;61 this.msg = msg;62 this.fn = fn;65 this.receiver = receiver; 66 this.msg = msg; 67 this.fn = fn; 63 68 } 64 69 static inline void ?{}( request & this, request & copy ) { 65 this.receiver = copy.receiver;66 this.msg = copy.msg;67 this.fn = copy.fn;70 this.receiver = copy.receiver; 71 this.msg = copy.msg; 72 this.fn = copy.fn; 68 73 } 69 74 … … 71 76 // assumes gulping behaviour (once a remove occurs, removes happen until empty beforw next insert) 72 77 struct copy_queue { 73 request * buffer;74 size_t count, buffer_size, index, utilized, last_size;78 request * buffer; 79 size_t count, buffer_size, index, utilized, last_size; 75 80 }; 76 81 static inline void ?{}( copy_queue & this ) {} 77 82 static inline void ?{}( copy_queue & this, size_t buf_size ) with(this) { 78 buffer_size = buf_size;79 buffer = aalloc( buffer_size );80 count = 0;81 utilized = 0;82 index = 0;83 last_size = 0;83 buffer_size = buf_size; 84 buffer = aalloc( buffer_size ); 85 count = 0; 86 utilized = 0; 87 index = 0; 88 last_size = 0; 84 89 } 85 90 static inline void ^?{}( copy_queue & this ) with(this) { 86 DEBUG_ABORT( count != 0, "Actor system terminated with messages sent but not received\n" );87 adelete(buffer);91 DEBUG_ABORT( count != 0, "Actor system terminated with messages sent but not received\n" ); 92 adelete(buffer); 88 93 } 89 94 90 95 static inline void insert( copy_queue & this, request & elem ) with(this) { 91 if ( count >= buffer_size ) { // increase arr size92 last_size = buffer_size;93 buffer_size = 2 * buffer_size;94 buffer = realloc( buffer, sizeof( request ) * buffer_size );95 /* paranoid */ verify( buffer );96 }97 memcpy( &buffer[count], &elem, sizeof(request) );98 count++;96 if ( count >= buffer_size ) { // increase arr size 97 last_size = buffer_size; 98 buffer_size = 2 * buffer_size; 99 buffer = realloc( buffer, sizeof( request ) * buffer_size ); 100 /* paranoid */ verify( buffer ); 101 } 102 memcpy( &buffer[count], &elem, sizeof(request) ); 103 count++; 99 104 } 100 105 … … 102 107 // it is not supported to call insert() before the array is fully empty 103 108 static inline request & remove( copy_queue & this ) with(this) { 104 if ( count > 0 ) {105 count--;106 size_t old_idx = index;107 index = count == 0 ? 0 : index + 1;108 return buffer[old_idx];109 }110 request * ret = 0p;111 return *0p;109 if ( count > 0 ) { 110 count--; 111 size_t old_idx = index; 112 index = count == 0 ? 0 : index + 1; 113 return buffer[old_idx]; 114 } 115 request * ret = 0p; 116 return *0p; 112 117 } 113 118 114 119 // try to reclaim some memory if less than half of buffer is utilized 115 120 static inline void reclaim( copy_queue & this ) with(this) { 116 if ( utilized >= last_size || buffer_size <= 4 ) { utilized = 0; return; }117 utilized = 0;118 buffer_size--;119 buffer = realloc( buffer, sizeof( request ) * buffer_size ); // try to reclaim some memory121 if ( utilized >= last_size || buffer_size <= 4 ) { utilized = 0; return; } 122 utilized = 0; 123 buffer_size--; 124 buffer = realloc( buffer, sizeof( request ) * buffer_size ); // try to reclaim some memory 120 125 } 121 126 … … 123 128 124 129 struct work_queue { 125 __spinlock_t mutex_lock; 126 copy_queue * owned_queue; // copy queue allocated and cleaned up by this work_queue 127 copy_queue * c_queue; // current queue 128 volatile bool being_processed; // flag to prevent concurrent processing 129 #ifdef ACTOR_STATS 130 unsigned int id; 131 size_t missed; // transfers skipped due to being_processed flag being up 130 __spinlock_t mutex_lock; 131 copy_queue * owned_queue; // copy queue allocated and cleaned up by this work_queue 132 copy_queue * c_queue; // current queue 133 volatile bool being_processed; // flag to prevent concurrent processing 134 #ifdef ACTOR_STATS 135 unsigned int id; 132 136 #endif 137 #ifdef ACTOR_STATS_QUEUE_MISSED 138 size_t missed; // transfers skipped due to being_processed flag being up 139 #endif 133 140 }; // work_queue 134 141 static inline void ?{}( work_queue & this, size_t buf_size, unsigned int i ) with(this) { 135 owned_queue = alloc();// allocated separately to avoid false sharing136 (*owned_queue){ buf_size };137 c_queue = owned_queue;138 being_processed = false;139 #ifdef ACTOR_STATS140 id = i;141 missed = 0;142 #endif142 owned_queue = alloc(); // allocated separately to avoid false sharing 143 (*owned_queue){ buf_size }; 144 c_queue = owned_queue; 145 being_processed = false; 146 #ifdef ACTOR_STATS 147 id = i; 148 missed = 0; 149 #endif 143 150 } 144 151 … … 147 154 148 155 static inline void insert( work_queue & this, request & elem ) with(this) { 149 lock( mutex_lock __cfaabi_dbg_ctx2 );150 insert( *c_queue, elem );151 unlock( mutex_lock );156 lock( mutex_lock __cfaabi_dbg_ctx2 ); 157 insert( *c_queue, elem ); 158 unlock( mutex_lock ); 152 159 } // insert 153 160 154 161 static inline void transfer( work_queue & this, copy_queue ** transfer_to ) with(this) { 155 lock( mutex_lock __cfaabi_dbg_ctx2 );156 #ifdef __STEAL157 158 // check if queue is being processed elsewhere159 if ( unlikely( being_processed ) ) {160 #ifdef ACTOR_STATS161 missed++;162 #endif163 unlock( mutex_lock );164 return;165 }166 167 being_processed = c_queue->count != 0;168 #endif // __STEAL169 170 c_queue->utilized = c_queue->count;171 172 // swap copy queue ptrs173 copy_queue * temp = *transfer_to;174 *transfer_to = c_queue;175 c_queue = temp;176 unlock( mutex_lock );162 lock( mutex_lock __cfaabi_dbg_ctx2 ); 163 #ifdef __STEAL 164 165 // check if queue is being processed elsewhere 166 if ( unlikely( being_processed ) ) { 167 #ifdef ACTOR_STATS 168 missed++; 169 #endif 170 unlock( mutex_lock ); 171 return; 172 } 173 174 being_processed = c_queue->count != 0; 175 #endif // __STEAL 176 177 c_queue->utilized = c_queue->count; 178 179 // swap copy queue ptrs 180 copy_queue * temp = *transfer_to; 181 *transfer_to = c_queue; 182 c_queue = temp; 183 unlock( mutex_lock ); 177 184 } // transfer 178 185 179 186 // needed since some info needs to persist past worker lifetimes 180 187 struct worker_info { 181 volatile unsigned long long stamp;182 #ifdef ACTOR_STATS183 size_t stolen_from, try_steal, stolen, empty_stolen, failed_swaps, msgs_stolen;184 unsigned long long processed;185 size_t gulps;186 #endif188 volatile unsigned long long stamp; 189 #ifdef ACTOR_STATS 190 size_t stolen_from, try_steal, stolen, empty_stolen, failed_swaps, msgs_stolen; 191 unsigned long long processed; 192 size_t gulps; 193 #endif 187 194 }; 188 195 static inline void ?{}( worker_info & this ) { 189 #ifdef ACTOR_STATS190 this.stolen_from = 0;191 this.try_steal = 0;// attempts to steal192 this.stolen = 0;// successful steals193 this.processed = 0;// requests processed194 this.gulps = 0;// number of gulps195 this.failed_swaps = 0;// steal swap failures196 this.empty_stolen = 0;// queues empty after steal197 this.msgs_stolen = 0;// number of messages stolen198 #endif199 this.stamp = rdtscl();196 #ifdef ACTOR_STATS 197 this.stolen_from = 0; 198 this.try_steal = 0; // attempts to steal 199 this.stolen = 0; // successful steals 200 this.processed = 0; // requests processed 201 this.gulps = 0; // number of gulps 202 this.failed_swaps = 0; // steal swap failures 203 this.empty_stolen = 0; // queues empty after steal 204 this.msgs_stolen = 0; // number of messages stolen 205 #endif 206 this.stamp = rdtscl(); 200 207 } 201 208 … … 205 212 // #endif 206 213 thread worker { 207 work_queue ** request_queues;208 copy_queue * current_queue;209 executor * executor_;210 unsigned int start, range;211 int id;214 work_queue ** request_queues; 215 copy_queue * current_queue; 216 executor * executor_; 217 unsigned int start, range; 218 int id; 212 219 }; 213 220 … … 215 222 // aggregate counters for statistics 216 223 size_t __total_tries = 0, __total_stolen = 0, __total_workers, __all_gulps = 0, __total_empty_stolen = 0, 217 __total_failed_swaps = 0, __all_processed = 0, __num_actors_stats = 0, __all_msgs_stolen = 0;224 __total_failed_swaps = 0, __all_processed = 0, __num_actors_stats = 0, __all_msgs_stolen = 0; 218 225 #endif 219 226 static inline void ?{}( worker & this, cluster & clu, work_queue ** request_queues, copy_queue * current_queue, executor * executor_, 220 unsigned int start, unsigned int range, int id ) {221 ((thread &)this){ clu };222 this.request_queues = request_queues;// array of all queues223 this.current_queue = current_queue;// currently gulped queue (start with empty queue to use in swap later)224 this.executor_ = executor_;// pointer to current executor225 this.start = start;// start of worker's subrange of request_queues226 this.range = range;// size of worker's subrange of request_queues227 this.id = id;// worker's id and index in array of workers227 unsigned int start, unsigned int range, int id ) { 228 ((thread &)this){ clu }; 229 this.request_queues = request_queues; // array of all queues 230 this.current_queue = current_queue; // currently gulped queue (start with empty queue to use in swap later) 231 this.executor_ = executor_; // pointer to current executor 232 this.start = start; // start of worker's subrange of request_queues 233 this.range = range; // size of worker's subrange of request_queues 234 this.id = id; // worker's id and index in array of workers 228 235 } 229 236 230 237 static bool no_steal = false; 231 238 struct executor { 232 cluster * cluster;// if workers execute on separate cluster233 processor ** processors; // array of virtual processors adding parallelism for workers234 work_queue * request_queues; // master array of work request queues235 copy_queue * local_queues;// array of all worker local queues to avoid deletion race236 work_queue ** worker_req_queues; // secondary array of work queues to allow for swapping237 worker ** workers;// array of workers executing work requests238 worker_info * w_infos;// array of info about each worker239 unsigned int nprocessors, nworkers, nrqueues; // number of processors/threads/request queues240 bool seperate_clus; // use same or separate cluster for executor241 volatile bool is_shutdown;// flag to communicate shutdown to worker threads239 cluster * cluster; // if workers execute on separate cluster 240 processor ** processors; // array of virtual processors adding parallelism for workers 241 work_queue * request_queues; // master array of work request queues 242 copy_queue * local_queues; // array of all worker local queues to avoid deletion race 243 work_queue ** worker_req_queues; // secondary array of work queues to allow for swapping 244 worker ** workers; // array of workers executing work requests 245 worker_info * w_infos; // array of info about each worker 246 unsigned int nprocessors, nworkers, nrqueues; // number of processors/threads/request queues 247 bool seperate_clus; // use same or separate cluster for executor 248 volatile bool is_shutdown; // flag to communicate shutdown to worker threads 242 249 }; // executor 243 250 … … 246 253 // #endif 247 254 static inline void ^?{}( worker & mutex this ) with(this) { 248 #ifdef ACTOR_STATS249 __atomic_add_fetch(&__all_gulps, executor_->w_infos[id].gulps,__ATOMIC_SEQ_CST);250 __atomic_add_fetch(&__all_processed, executor_->w_infos[id].processed,__ATOMIC_SEQ_CST);251 __atomic_add_fetch(&__all_msgs_stolen, executor_->w_infos[id].msgs_stolen,__ATOMIC_SEQ_CST);252 __atomic_add_fetch(&__total_tries, executor_->w_infos[id].try_steal, __ATOMIC_SEQ_CST);253 __atomic_add_fetch(&__total_stolen, executor_->w_infos[id].stolen, __ATOMIC_SEQ_CST);254 __atomic_add_fetch(&__total_failed_swaps, executor_->w_infos[id].failed_swaps, __ATOMIC_SEQ_CST);255 __atomic_add_fetch(&__total_empty_stolen, executor_->w_infos[id].empty_stolen, __ATOMIC_SEQ_CST);256 257 // per worker steal stats (uncomment alongside the lock above this routine to print)258 // lock( out_lock __cfaabi_dbg_ctx2 );259 // printf("Worker id: %d, processed: %llu messages, attempted %lu, stole: %lu, stolen from: %lu\n", id, processed, try_steal, stolen, __atomic_add_fetch(&executor_->w_infos[id].stolen_from, 0, __ATOMIC_SEQ_CST) );260 // int count = 0;261 // int count2 = 0;262 // for ( i; range ) {263 //if ( replaced_queue[start + i] > 0 ){264 //count++;265 //// printf("%d: %u, ",i, replaced_queue[i]);266 //}267 //if (__atomic_add_fetch(&stolen_arr[start + i],0,__ATOMIC_SEQ_CST) > 0)268 //count2++;269 // }270 // printf("swapped with: %d of %u indices\n", count, executor_->nrqueues / executor_->nworkers );271 // printf("%d of %u indices were stolen\n", count2, executor_->nrqueues / executor_->nworkers );272 // unlock( out_lock );273 #endif255 #ifdef ACTOR_STATS 256 __atomic_add_fetch(&__all_gulps, executor_->w_infos[id].gulps,__ATOMIC_SEQ_CST); 257 __atomic_add_fetch(&__all_processed, executor_->w_infos[id].processed,__ATOMIC_SEQ_CST); 258 __atomic_add_fetch(&__all_msgs_stolen, executor_->w_infos[id].msgs_stolen,__ATOMIC_SEQ_CST); 259 __atomic_add_fetch(&__total_tries, executor_->w_infos[id].try_steal, __ATOMIC_SEQ_CST); 260 __atomic_add_fetch(&__total_stolen, executor_->w_infos[id].stolen, __ATOMIC_SEQ_CST); 261 __atomic_add_fetch(&__total_failed_swaps, executor_->w_infos[id].failed_swaps, __ATOMIC_SEQ_CST); 262 __atomic_add_fetch(&__total_empty_stolen, executor_->w_infos[id].empty_stolen, __ATOMIC_SEQ_CST); 263 264 // per worker steal stats (uncomment alongside the lock above this routine to print) 265 // lock( out_lock __cfaabi_dbg_ctx2 ); 266 // printf("Worker id: %d, processed: %llu messages, attempted %lu, stole: %lu, stolen from: %lu\n", id, processed, try_steal, stolen, __atomic_add_fetch(&executor_->w_infos[id].stolen_from, 0, __ATOMIC_SEQ_CST) ); 267 // int count = 0; 268 // int count2 = 0; 269 // for ( i; range ) { 270 // if ( replaced_queue[start + i] > 0 ){ 271 // count++; 272 // // printf("%d: %u, ",i, replaced_queue[i]); 273 // } 274 // if (__atomic_add_fetch(&stolen_arr[start + i],0,__ATOMIC_SEQ_CST) > 0) 275 // count2++; 276 // } 277 // printf("swapped with: %d of %u indices\n", count, executor_->nrqueues / executor_->nworkers ); 278 // printf("%d of %u indices were stolen\n", count2, executor_->nrqueues / executor_->nworkers ); 279 // unlock( out_lock ); 280 #endif 274 281 } 275 282 276 283 static inline void ?{}( executor & this, unsigned int nprocessors, unsigned int nworkers, unsigned int nrqueues, bool seperate_clus, size_t buf_size ) with(this) { 277 if ( nrqueues < nworkers ) abort( "nrqueues needs to be >= nworkers\n" );278 this.nprocessors = nprocessors;279 this.nworkers = nworkers;280 this.nrqueues = nrqueues;281 this.seperate_clus = seperate_clus;282 this.is_shutdown = false;283 284 if ( nworkers == nrqueues )285 no_steal = true;286 287 #ifdef ACTOR_STATS288 // stolen_arr = aalloc( nrqueues );289 // replaced_queue = aalloc( nrqueues );290 __total_workers = nworkers;291 #endif292 293 if ( seperate_clus ) {294 cluster = alloc();295 (*cluster){};296 } else cluster = active_cluster();297 298 request_queues = aalloc( nrqueues );299 worker_req_queues = aalloc( nrqueues );300 for ( i; nrqueues ) {301 request_queues[i]{ buf_size, i };302 worker_req_queues[i] = &request_queues[i];303 }304 305 processors = aalloc( nprocessors );306 for ( i; nprocessors )307 (*(processors[i] = alloc())){ *cluster };308 309 local_queues = aalloc( nworkers );310 workers = aalloc( nworkers );311 w_infos = aalloc( nworkers );312 unsigned int reqPerWorker = nrqueues / nworkers, extras = nrqueues % nworkers;313 314 for ( i; nworkers ) {315 w_infos[i]{};316 local_queues[i]{ buf_size };317 }318 319 for ( unsigned int i = 0, start = 0, range; i < nworkers; i += 1, start += range ) {320 range = reqPerWorker + ( i < extras ? 1 : 0 );321 (*(workers[i] = alloc())){ *cluster, worker_req_queues, &local_queues[i], &this, start, range, i };322 } // for284 if ( nrqueues < nworkers ) abort( "nrqueues needs to be >= nworkers\n" ); 285 this.nprocessors = nprocessors; 286 this.nworkers = nworkers; 287 this.nrqueues = nrqueues; 288 this.seperate_clus = seperate_clus; 289 this.is_shutdown = false; 290 291 if ( nworkers == nrqueues ) 292 no_steal = true; 293 294 #ifdef ACTOR_STATS 295 // stolen_arr = aalloc( nrqueues ); 296 // replaced_queue = aalloc( nrqueues ); 297 __total_workers = nworkers; 298 #endif 299 300 if ( seperate_clus ) { 301 cluster = alloc(); 302 (*cluster){}; 303 } else cluster = active_cluster(); 304 305 request_queues = aalloc( nrqueues ); 306 worker_req_queues = aalloc( nrqueues ); 307 for ( i; nrqueues ) { 308 request_queues[i]{ buf_size, i }; 309 worker_req_queues[i] = &request_queues[i]; 310 } 311 312 processors = aalloc( nprocessors ); 313 for ( i; nprocessors ) 314 (*(processors[i] = alloc())){ *cluster }; 315 316 local_queues = aalloc( nworkers ); 317 workers = aalloc( nworkers ); 318 w_infos = aalloc( nworkers ); 319 unsigned int reqPerWorker = nrqueues / nworkers, extras = nrqueues % nworkers; 320 321 for ( i; nworkers ) { 322 w_infos[i]{}; 323 local_queues[i]{ buf_size }; 324 } 325 326 for ( unsigned int i = 0, start = 0, range; i < nworkers; i += 1, start += range ) { 327 range = reqPerWorker + ( i < extras ? 1 : 0 ); 328 (*(workers[i] = alloc())){ *cluster, worker_req_queues, &local_queues[i], &this, start, range, i }; 329 } // for 323 330 } 324 331 static inline void ?{}( executor & this, unsigned int nprocessors, unsigned int nworkers, unsigned int nrqueues, bool seperate_clus ) { this{ nprocessors, nworkers, nrqueues, seperate_clus, __DEFAULT_EXECUTOR_BUFSIZE__ }; } … … 329 336 330 337 static inline void ^?{}( executor & this ) with(this) { 331 is_shutdown = true; 332 333 for ( i; nworkers ) 334 delete( workers[i] ); 335 336 for ( i; nprocessors ) { 337 delete( processors[i] ); 338 } // for 339 340 #ifdef ACTOR_STATS 341 size_t misses = 0; 342 for ( i; nrqueues ) { 343 misses += worker_req_queues[i]->missed; 344 } 345 // adelete( stolen_arr ); 346 // adelete( replaced_queue ); 338 is_shutdown = true; 339 340 for ( i; nworkers ) 341 delete( workers[i] ); 342 343 for ( i; nprocessors ) { 344 delete( processors[i] ); 345 } // for 346 347 #ifdef ACTOR_STATS_QUEUE_MISSED 348 size_t misses = 0; 349 for ( i; nrqueues ) { 350 misses += worker_req_queues[i]->missed; 351 } 352 // adelete( stolen_arr ); 353 // adelete( replaced_queue ); 354 #endif 355 356 adelete( workers ); 357 adelete( w_infos ); 358 adelete( local_queues ); 359 adelete( request_queues ); 360 adelete( worker_req_queues ); 361 adelete( processors ); 362 if ( seperate_clus ) delete( cluster ); 363 364 #ifdef ACTOR_STATS // print formatted stats 365 printf(" Actor System Stats:\n"); 366 printf("\tActors Created:\t\t\t\t%lu\n\tMessages Sent:\t\t\t\t%lu\n", __num_actors_stats, __all_processed); 367 size_t avg_gulps = __all_gulps == 0 ? 0 : __all_processed / __all_gulps; 368 printf("\tGulps:\t\t\t\t\t%lu\n\tAverage Gulp Size:\t\t\t%lu\n\tMissed gulps:\t\t\t\t%lu\n", __all_gulps, avg_gulps, misses); 369 printf("\tSteal attempts:\t\t\t\t%lu\n\tSteals:\t\t\t\t\t%lu\n\tSteal failures (no candidates):\t\t%lu\n\tSteal failures (failed swaps):\t\t%lu\t Empty steals:\t\t%lu\n", 370 __total_tries, __total_stolen, __total_tries - __total_stolen - __total_failed_swaps, __total_failed_swaps, __total_empty_stolen); 371 size_t avg_steal = __total_stolen == 0 ? 0 : __all_msgs_stolen / __total_stolen; 372 printf("\tMessages stolen:\t\t\t%lu\n\tAverage steal size:\t\t\t%lu\n", __all_msgs_stolen, avg_steal); 373 #endif 374 375 #ifndef ACTOR_STATS 376 #ifdef ACTOR_STATS_QUEUE_MISSED 377 printf("\t%lu", misses); 347 378 #endif 348 349 adelete( workers );350 adelete( w_infos );351 adelete( local_queues );352 adelete( request_queues );353 adelete( worker_req_queues );354 adelete( processors );355 if ( seperate_clus ) delete( cluster );356 357 #ifdef ACTOR_STATS // print formatted stats358 printf(" Actor System Stats:\n");359 printf("\tActors Created:\t\t\t\t%lu\n\tMessages Sent:\t\t\t\t%lu\n", __num_actors_stats, __all_processed);360 size_t avg_gulps = __all_gulps == 0 ? 0 : __all_processed / __all_gulps;361 printf("\tGulps:\t\t\t\t\t%lu\n\tAverage Gulp Size:\t\t\t%lu\n\tMissed gulps:\t\t\t\t%lu\n", __all_gulps, avg_gulps, misses);362 printf("\tSteal attempts:\t\t\t\t%lu\n\tSteals:\t\t\t\t\t%lu\n\tSteal failures (no candidates):\t\t%lu\n\tSteal failures (failed swaps):\t\t%lu\t Empty steals:\t\t%lu\n",363 __total_tries, __total_stolen, __total_tries - __total_stolen - __total_failed_swaps, __total_failed_swaps, __total_empty_stolen);364 size_t avg_steal = __total_stolen == 0 ? 0 : __all_msgs_stolen / __total_stolen;365 printf("\tMessages stolen:\t\t\t%lu\n\tAverage steal size:\t\t\t%lu\n", __all_msgs_stolen, avg_steal);366 379 #endif 367 380 368 381 } 369 382 … … 372 385 373 386 static inline size_t __get_next_ticket( executor & this ) with(this) { 374 #ifdef __CFA_DEBUG__375 size_t temp = __atomic_fetch_add( &__next_ticket, 1, __ATOMIC_SEQ_CST) % nrqueues;376 377 // reserve MAX for dead actors378 if ( unlikely( temp == MAX ) ) temp = __atomic_fetch_add( &__next_ticket, 1, __ATOMIC_SEQ_CST) % nrqueues;379 return temp;380 #else381 return __atomic_fetch_add( &__next_ticket, 1, __ATOMIC_RELAXED) % nrqueues;382 #endif387 #ifdef __CFA_DEBUG__ 388 size_t temp = __atomic_fetch_add( &__next_ticket, 1, __ATOMIC_SEQ_CST) % nrqueues; 389 390 // reserve MAX for dead actors 391 if ( unlikely( temp == MAX ) ) temp = __atomic_fetch_add( &__next_ticket, 1, __ATOMIC_SEQ_CST) % nrqueues; 392 return temp; 393 #else 394 return __atomic_fetch_add( &__next_ticket, 1, __ATOMIC_RELAXED) % nrqueues; 395 #endif 383 396 } // tickets 384 397 385 398 // TODO: update globals in this file to be static fields once the static fields project is done 386 399 static executor * __actor_executor_ = 0p; 387 static bool __actor_executor_passed = false; // was an executor passed to start_actor_system388 static size_t __num_actors_ = 0; // number of actor objects in system400 static bool __actor_executor_passed = false; // was an executor passed to start_actor_system 401 static size_t __num_actors_ = 0; // number of actor objects in system 389 402 static struct thread$ * __actor_executor_thd = 0p; // used to wake executor after actors finish 390 403 struct actor { 391 size_t ticket;// executor-queue handle392 allocation allocation_;// allocation action393 inline virtual_dtor;404 size_t ticket; // executor-queue handle 405 allocation alloc; // allocation action 406 inline virtual_dtor; 394 407 }; 395 408 396 409 static inline void ?{}( actor & this ) with(this) { 397 // Once an actor is allocated it must be sent a message or the actor system cannot stop. Hence, its receive398 // member must be called to end it399 DEBUG_ABORT( __actor_executor_ == 0p, "Creating actor before calling start_actor_system() can cause undefined behaviour.\n" );400 allocation_= Nodelete;401 ticket = __get_next_ticket( *__actor_executor_ );402 __atomic_fetch_add( &__num_actors_, 1, __ATOMIC_RELAXED );403 #ifdef ACTOR_STATS404 __atomic_fetch_add( &__num_actors_stats, 1, __ATOMIC_SEQ_CST );405 #endif410 // Once an actor is allocated it must be sent a message or the actor system cannot stop. Hence, its receive 411 // member must be called to end it 412 DEBUG_ABORT( __actor_executor_ == 0p, "Creating actor before calling start_actor_system() can cause undefined behaviour.\n" ); 413 alloc = Nodelete; 414 ticket = __get_next_ticket( *__actor_executor_ ); 415 __atomic_fetch_add( &__num_actors_, 1, __ATOMIC_RELAXED ); 416 #ifdef ACTOR_STATS 417 __atomic_fetch_add( &__num_actors_stats, 1, __ATOMIC_SEQ_CST ); 418 #endif 406 419 } 407 420 408 421 static inline void check_actor( actor & this ) { 409 if ( this.allocation_!= Nodelete ) {410 switch( this.allocation_) {411 case Delete: delete( &this ); break;412 case Destroy:413 CFA_DEBUG( this.ticket = MAX; );// mark as terminated414 ^?{}(this);415 break;416 case Finished:417 CFA_DEBUG( this.ticket = MAX; );// mark as terminated418 break;419 default: ;// stop warning420 }421 422 if ( unlikely( __atomic_add_fetch( &__num_actors_, -1, __ATOMIC_RELAXED ) == 0 ) ) { // all actors have terminated423 unpark( __actor_executor_thd );424 }425 }422 if ( this.alloc != Nodelete ) { 423 switch( this.alloc ) { 424 case Delete: delete( &this ); break; 425 case Destroy: 426 CFA_DEBUG( this.ticket = MAX; ); // mark as terminated 427 ^?{}(this); 428 break; 429 case Finished: 430 CFA_DEBUG( this.ticket = MAX; ); // mark as terminated 431 break; 432 default: ; // stop warning 433 } 434 435 if ( unlikely( __atomic_add_fetch( &__num_actors_, -1, __ATOMIC_RELAXED ) == 0 ) ) { // all actors have terminated 436 unpark( __actor_executor_thd ); 437 } 438 } 426 439 } 427 440 428 441 struct message { 429 allocation allocation_;// allocation action430 inline virtual_dtor;442 allocation alloc; // allocation action 443 inline virtual_dtor; 431 444 }; 432 445 433 446 static inline void ?{}( message & this ) { 434 this.allocation_= Nodelete;447 this.alloc = Nodelete; 435 448 } 436 449 static inline void ?{}( message & this, allocation alloc ) { 437 memcpy( &this.allocation_, &alloc, sizeof(allocation) );// optimization to elide ctor438 DEBUG_ABORT( this.allocation_ == Finished, "The Finished allocation status is not supported for message types.\n");450 memcpy( &this.alloc, &alloc, sizeof(allocation) ); // optimization to elide ctor 451 CFA_DEBUG( if ( this.alloc == Finished ) this.alloc = Nodelete; ); 439 452 } 440 453 static inline void ^?{}( message & this ) with(this) { 441 CFA_DEBUG( if ( allocation_ == Nodelete ) printf("A message at location %p was allocated but never sent.\n", &this); ) 454 CFA_DEBUG( 455 if ( alloc == Nodelete ) { 456 printf( "CFA warning (UNIX pid:%ld) : program terminating with message %p allocated but never sent.\n", 457 (long int)getpid(), &this ); 458 } 459 ) 442 460 } 443 461 444 462 static inline void check_message( message & this ) { 445 switch ( this.allocation_ ) { // analyze message status 446 case Nodelete: CFA_DEBUG( this.allocation_ = Finished ); break; 447 case Delete: delete( &this ); break; 448 case Destroy: ^?{}( this ); break; 449 case Finished: break; 450 } // switch 451 } 452 static inline void set_allocation( message & this, allocation state ) { 453 this.allocation_ = state; 463 switch ( this.alloc ) { // analyze message status 464 case Nodelete: CFA_DEBUG( this.alloc = Finished ); break; 465 case Delete: delete( &this ); break; 466 case Destroy: ^?{}( this ); break; 467 case Finished: break; 468 } // switch 469 } 470 static inline allocation set_allocation( message & this, allocation state ) { 471 CFA_DEBUG( if ( state == Nodelete ) state = Finished; ); 472 allocation prev = this.alloc; 473 this.alloc = state; 474 return prev; 475 } 476 static inline allocation get_allocation( message & this ) { 477 return this.alloc; 454 478 } 455 479 456 480 static inline void deliver_request( request & this ) { 457 DEBUG_ABORT( this.receiver->ticket == (unsigned long int)MAX, "Attempted to send message to deleted/dead actor\n" );458 actor * base_actor;459 message * base_msg;460 allocation temp = this.fn( *this.receiver, *this.msg, &base_actor, &base_msg );461 base_actor->allocation_ = temp; 462 check_message( *base_msg );463 check_actor( *base_actor );481 DEBUG_ABORT( this.receiver->ticket == (unsigned long int)MAX, "Attempted to send message to deleted/dead actor\n" ); 482 actor * base_actor; 483 message * base_msg; 484 allocation temp = this.fn( *this.receiver, *this.msg, &base_actor, &base_msg ); 485 memcpy( &base_actor->alloc, &temp, sizeof(allocation) ); // optimization to elide ctor 486 check_message( *base_msg ); 487 check_actor( *base_actor ); 464 488 } 465 489 … … 467 491 // returns ptr to newly owned queue if swap succeeds 468 492 static inline work_queue * try_swap_queues( worker & this, unsigned int victim_idx, unsigned int my_idx ) with(this) { 469 work_queue * my_queue = request_queues[my_idx];470 work_queue * other_queue = request_queues[victim_idx];471 472 // if either queue is 0p then they are in the process of being stolen473 if ( other_queue == 0p ) return 0p;474 475 // try to set our queue ptr to be 0p. If it fails someone moved our queue so return false476 if ( !__atomic_compare_exchange_n( &request_queues[my_idx], &my_queue, 0p, false, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST ) )477 return 0p;478 479 // try to set other queue ptr to be our queue ptr. If it fails someone moved the other queue so fix up then return false480 if ( !__atomic_compare_exchange_n( &request_queues[victim_idx], &other_queue, my_queue, false, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST ) ) {481 /* paranoid */ verify( request_queues[my_idx] == 0p );482 request_queues[my_idx] = my_queue; // reset my queue ptr back to appropriate val483 return 0p;484 }485 486 // we have successfully swapped and since our queue is 0p no one will touch it so write back new queue ptr non atomically487 request_queues[my_idx] = other_queue; // last write does not need to be atomic488 return other_queue;493 work_queue * my_queue = request_queues[my_idx]; 494 work_queue * other_queue = request_queues[victim_idx]; 495 496 // if either queue is 0p then they are in the process of being stolen 497 if ( other_queue == 0p ) return 0p; 498 499 // try to set our queue ptr to be 0p. If it fails someone moved our queue so return false 500 if ( !__atomic_compare_exchange_n( &request_queues[my_idx], &my_queue, 0p, false, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST ) ) 501 return 0p; 502 503 // try to set other queue ptr to be our queue ptr. If it fails someone moved the other queue so fix up then return false 504 if ( !__atomic_compare_exchange_n( &request_queues[victim_idx], &other_queue, my_queue, false, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST ) ) { 505 /* paranoid */ verify( request_queues[my_idx] == 0p ); 506 request_queues[my_idx] = my_queue; // reset my queue ptr back to appropriate val 507 return 0p; 508 } 509 510 // we have successfully swapped and since our queue is 0p no one will touch it so write back new queue ptr non atomically 511 request_queues[my_idx] = other_queue; // last write does not need to be atomic 512 return other_queue; 489 513 } 490 514 491 515 // once a worker to steal from has been chosen, choose queue to steal from 492 516 static inline void choose_queue( worker & this, unsigned int victim_id, unsigned int swap_idx ) with(this) { 493 // have to calculate victim start and range since victim may be deleted before us in shutdown494 const unsigned int queues_per_worker = executor_->nrqueues / executor_->nworkers;495 const unsigned int extras = executor_->nrqueues % executor_->nworkers;496 unsigned int vic_start, vic_range;497 if ( extras > victim_id ) {498 vic_range = queues_per_worker + 1;499 vic_start = vic_range * victim_id;500 } else {501 vic_start = extras + victim_id * queues_per_worker;502 vic_range = queues_per_worker;503 }504 unsigned int start_idx = prng( vic_range );505 506 unsigned int tries = 0;507 work_queue * curr_steal_queue;508 509 for ( unsigned int i = start_idx; tries < vic_range; i = (i + 1) % vic_range ) {510 tries++;511 curr_steal_queue = request_queues[ i + vic_start ];512 // avoid empty queues and queues that are being operated on513 if ( curr_steal_queue == 0p || curr_steal_queue->being_processed || is_empty( *curr_steal_queue->c_queue ) )514 continue;515 516 #ifdef ACTOR_STATS517 curr_steal_queue = try_swap_queues( this, i + vic_start, swap_idx );518 if ( curr_steal_queue ) {519 executor_->w_infos[id].msgs_stolen += curr_steal_queue->c_queue->count;520 executor_->w_infos[id].stolen++;521 if ( is_empty( *curr_steal_queue->c_queue ) ) executor_->w_infos[id].empty_stolen++;522 // __atomic_add_fetch(&executor_->w_infos[victim_id].stolen_from, 1, __ATOMIC_RELAXED);523 // replaced_queue[swap_idx]++;524 // __atomic_add_fetch(&stolen_arr[ i + vic_start ], 1, __ATOMIC_RELAXED);525 } else {526 executor_->w_infos[id].failed_swaps++;527 }528 #else529 curr_steal_queue = try_swap_queues( this, i + vic_start, swap_idx );530 #endif // ACTOR_STATS531 532 return;533 }534 535 return;517 // have to calculate victim start and range since victim may be deleted before us in shutdown 518 const unsigned int queues_per_worker = executor_->nrqueues / executor_->nworkers; 519 const unsigned int extras = executor_->nrqueues % executor_->nworkers; 520 unsigned int vic_start, vic_range; 521 if ( extras > victim_id ) { 522 vic_range = queues_per_worker + 1; 523 vic_start = vic_range * victim_id; 524 } else { 525 vic_start = extras + victim_id * queues_per_worker; 526 vic_range = queues_per_worker; 527 } 528 unsigned int start_idx = prng( vic_range ); 529 530 unsigned int tries = 0; 531 work_queue * curr_steal_queue; 532 533 for ( unsigned int i = start_idx; tries < vic_range; i = (i + 1) % vic_range ) { 534 tries++; 535 curr_steal_queue = request_queues[ i + vic_start ]; 536 // avoid empty queues and queues that are being operated on 537 if ( curr_steal_queue == 0p || curr_steal_queue->being_processed || is_empty( *curr_steal_queue->c_queue ) ) 538 continue; 539 540 #ifdef ACTOR_STATS 541 curr_steal_queue = try_swap_queues( this, i + vic_start, swap_idx ); 542 if ( curr_steal_queue ) { 543 executor_->w_infos[id].msgs_stolen += curr_steal_queue->c_queue->count; 544 executor_->w_infos[id].stolen++; 545 if ( is_empty( *curr_steal_queue->c_queue ) ) executor_->w_infos[id].empty_stolen++; 546 // __atomic_add_fetch(&executor_->w_infos[victim_id].stolen_from, 1, __ATOMIC_RELAXED); 547 // replaced_queue[swap_idx]++; 548 // __atomic_add_fetch(&stolen_arr[ i + vic_start ], 1, __ATOMIC_RELAXED); 549 } else { 550 executor_->w_infos[id].failed_swaps++; 551 } 552 #else 553 curr_steal_queue = try_swap_queues( this, i + vic_start, swap_idx ); 554 #endif // ACTOR_STATS 555 556 return; 557 } 558 559 return; 536 560 } 537 561 538 562 // choose a worker to steal from 539 563 static inline void steal_work( worker & this, unsigned int swap_idx ) with(this) { 540 #if RAND541 unsigned int victim = prng( executor_->nworkers );542 if ( victim == id ) victim = ( victim + 1 ) % executor_->nworkers;543 choose_queue( this, victim, swap_idx );544 #elif SEARCH545 unsigned long long min = MAX; // smaller timestamp means longer since service546 int min_id = 0; // use ints not uints to avoid integer underflow without hacky math547 int n_workers = executor_->nworkers;548 unsigned long long curr_stamp;549 int scount = 1;550 for ( int i = (id + 1) % n_workers; scount < n_workers; i = (i + 1) % n_workers, scount++ ) {551 curr_stamp = executor_->w_infos[i].stamp;552 if ( curr_stamp < min ) {553 min = curr_stamp;554 min_id = i;555 }556 }557 choose_queue( this, min_id, swap_idx );558 #endif564 #if RAND 565 unsigned int victim = prng( executor_->nworkers ); 566 if ( victim == id ) victim = ( victim + 1 ) % executor_->nworkers; 567 choose_queue( this, victim, swap_idx ); 568 #elif SEARCH 569 unsigned long long min = MAX; // smaller timestamp means longer since service 570 int min_id = 0; // use ints not uints to avoid integer underflow without hacky math 571 int n_workers = executor_->nworkers; 572 unsigned long long curr_stamp; 573 int scount = 1; 574 for ( int i = (id + 1) % n_workers; scount < n_workers; i = (i + 1) % n_workers, scount++ ) { 575 curr_stamp = executor_->w_infos[i].stamp; 576 if ( curr_stamp < min ) { 577 min = curr_stamp; 578 min_id = i; 579 } 580 } 581 choose_queue( this, min_id, swap_idx ); 582 #endif 559 583 } 560 584 561 585 #define CHECK_TERMINATION if ( unlikely( executor_->is_shutdown ) ) break Exit 562 586 void main( worker & this ) with(this) { 563 // #ifdef ACTOR_STATS 564 // for ( i; executor_->nrqueues ) { 565 // replaced_queue[i] = 0; 566 // __atomic_store_n( &stolen_arr[i], 0, __ATOMIC_SEQ_CST ); 567 // } 568 // #endif 569 570 // threshold of empty queues we see before we go stealing 571 const unsigned int steal_threshold = 2 * range; 572 573 // Store variable data here instead of worker struct to avoid any potential false sharing 574 unsigned int empty_count = 0; 575 request & req; 576 work_queue * curr_work_queue; 577 578 Exit: 579 for ( unsigned int i = 0;; i = (i + 1) % range ) { // cycle through set of request buffers 580 curr_work_queue = request_queues[i + start]; 581 582 // check if queue is empty before trying to gulp it 583 if ( is_empty( *curr_work_queue->c_queue ) ) { 584 #ifdef __STEAL 585 empty_count++; 586 if ( empty_count < steal_threshold ) continue; 587 #else 588 continue; 589 #endif 590 } 591 transfer( *curr_work_queue, ¤t_queue ); 592 #ifdef ACTOR_STATS 593 executor_->w_infos[id].gulps++; 594 #endif // ACTOR_STATS 595 #ifdef __STEAL 596 if ( is_empty( *current_queue ) ) { 597 if ( unlikely( no_steal ) ) { CHECK_TERMINATION; continue; } 598 empty_count++; 599 if ( empty_count < steal_threshold ) continue; 600 empty_count = 0; 601 602 CHECK_TERMINATION; // check for termination 603 604 __atomic_store_n( &executor_->w_infos[id].stamp, rdtscl(), __ATOMIC_RELAXED ); 605 606 #ifdef ACTOR_STATS 607 executor_->w_infos[id].try_steal++; 608 #endif // ACTOR_STATS 609 610 steal_work( this, start + prng( range ) ); 611 continue; 612 } 613 #endif // __STEAL 614 while ( ! is_empty( *current_queue ) ) { 615 #ifdef ACTOR_STATS 616 executor_->w_infos[id].processed++; 617 #endif 618 &req = &remove( *current_queue ); 619 if ( !&req ) continue; 620 deliver_request( req ); 621 } 622 #ifdef __STEAL 623 curr_work_queue->being_processed = false; // set done processing 624 empty_count = 0; // we found work so reset empty counter 587 // #ifdef ACTOR_STATS 588 // for ( i; executor_->nrqueues ) { 589 // replaced_queue[i] = 0; 590 // __atomic_store_n( &stolen_arr[i], 0, __ATOMIC_SEQ_CST ); 591 // } 592 // #endif 593 594 // threshold of empty queues we see before we go stealing 595 const unsigned int steal_threshold = 2 * range; 596 597 // Store variable data here instead of worker struct to avoid any potential false sharing 598 unsigned int empty_count = 0; 599 request & req; 600 work_queue * curr_work_queue; 601 602 Exit: 603 for ( unsigned int i = 0;; i = (i + 1) % range ) { // cycle through set of request buffers 604 curr_work_queue = request_queues[i + start]; 605 606 #ifndef __STEAL 607 CHECK_TERMINATION; 625 608 #endif 626 627 CHECK_TERMINATION; 628 629 // potentially reclaim some of the current queue's vector space if it is unused 630 reclaim( *current_queue ); 631 } // for 609 610 // check if queue is empty before trying to gulp it 611 if ( is_empty( *curr_work_queue->c_queue ) ) { 612 #ifdef __STEAL 613 empty_count++; 614 if ( empty_count < steal_threshold ) continue; 615 #else 616 continue; 617 #endif 618 } 619 transfer( *curr_work_queue, ¤t_queue ); 620 #ifdef ACTOR_STATS 621 executor_->w_infos[id].gulps++; 622 #endif // ACTOR_STATS 623 #ifdef __STEAL 624 if ( is_empty( *current_queue ) ) { 625 if ( unlikely( no_steal ) ) { CHECK_TERMINATION; continue; } 626 empty_count++; 627 if ( empty_count < steal_threshold ) continue; 628 empty_count = 0; 629 630 CHECK_TERMINATION; // check for termination 631 632 __atomic_store_n( &executor_->w_infos[id].stamp, rdtscl(), __ATOMIC_RELAXED ); 633 634 #ifdef ACTOR_STATS 635 executor_->w_infos[id].try_steal++; 636 #endif // ACTOR_STATS 637 638 steal_work( this, start + prng( range ) ); 639 continue; 640 } 641 #endif // __STEAL 642 while ( ! is_empty( *current_queue ) ) { 643 #ifdef ACTOR_STATS 644 executor_->w_infos[id].processed++; 645 #endif 646 &req = &remove( *current_queue ); 647 if ( !&req ) continue; 648 deliver_request( req ); 649 } 650 #ifdef __STEAL 651 curr_work_queue->being_processed = false; // set done processing 652 empty_count = 0; // we found work so reset empty counter 653 #endif 654 655 CHECK_TERMINATION; 656 657 // potentially reclaim some of the current queue's vector space if it is unused 658 reclaim( *current_queue ); 659 } // for 632 660 } 633 661 634 662 static inline void send( executor & this, request & req, unsigned long int ticket ) with(this) { 635 insert( request_queues[ticket], req);663 insert( request_queues[ticket], req); 636 664 } 637 665 638 666 static inline void send( actor & this, request & req ) { 639 DEBUG_ABORT( this.ticket == (unsigned long int)MAX, "Attempted to send message to deleted/dead actor\n" );640 send( *__actor_executor_, req, this.ticket );667 DEBUG_ABORT( this.ticket == (unsigned long int)MAX, "Attempted to send message to deleted/dead actor\n" ); 668 send( *__actor_executor_, req, this.ticket ); 641 669 } 642 670 643 671 static inline void __reset_stats() { 644 #ifdef ACTOR_STATS645 __total_tries = 0;646 __total_stolen = 0;647 __all_gulps = 0;648 __total_failed_swaps = 0;649 __total_empty_stolen = 0;650 __all_processed = 0;651 __num_actors_stats = 0;652 __all_msgs_stolen = 0;653 #endif672 #ifdef ACTOR_STATS 673 __total_tries = 0; 674 __total_stolen = 0; 675 __all_gulps = 0; 676 __total_failed_swaps = 0; 677 __total_empty_stolen = 0; 678 __all_processed = 0; 679 __num_actors_stats = 0; 680 __all_msgs_stolen = 0; 681 #endif 654 682 } 655 683 656 684 static inline void start_actor_system( size_t num_thds ) { 657 __reset_stats();658 __actor_executor_thd = active_thread();659 __actor_executor_ = alloc();660 (*__actor_executor_){ 0, num_thds, num_thds == 1 ? 1 : num_thds * 16 };685 __reset_stats(); 686 __actor_executor_thd = active_thread(); 687 __actor_executor_ = alloc(); 688 (*__actor_executor_){ 0, num_thds, num_thds == 1 ? 1 : num_thds * 16 }; 661 689 } 662 690 … … 664 692 665 693 static inline void start_actor_system( executor & this ) { 666 __reset_stats();667 __actor_executor_thd = active_thread();668 __actor_executor_ = &this;669 __actor_executor_passed = true;694 __reset_stats(); 695 __actor_executor_thd = active_thread(); 696 __actor_executor_ = &this; 697 __actor_executor_passed = true; 670 698 } 671 699 672 700 static inline void stop_actor_system() { 673 park( ); // will beunparked when actor system is finished674 675 if ( !__actor_executor_passed ) delete( __actor_executor_ );676 __actor_executor_ = 0p;677 __actor_executor_thd = 0p;678 __next_ticket = 0;679 __actor_executor_passed = false;701 park(); // unparked when actor system is finished 702 703 if ( !__actor_executor_passed ) delete( __actor_executor_ ); 704 __actor_executor_ = 0p; 705 __actor_executor_thd = 0p; 706 __next_ticket = 0; 707 __actor_executor_passed = false; 680 708 } 681 709 682 710 // Default messages to send to any actor to change status 683 711 // assigned at creation to __base_msg_finished to avoid unused message warning 684 message __base_msg_finished @= { .allocation_ : Finished }; 685 struct __delete_msg_t { inline message; } delete_msg = __base_msg_finished; 686 struct __destroy_msg_t { inline message; } destroy_msg = __base_msg_finished; 687 struct __finished_msg_t { inline message; } finished_msg = __base_msg_finished; 688 689 allocation receive( actor & this, __delete_msg_t & msg ) { return Delete; } 690 allocation receive( actor & this, __destroy_msg_t & msg ) { return Destroy; } 691 allocation receive( actor & this, __finished_msg_t & msg ) { return Finished; } 692 712 message __base_msg_finished @= { .alloc : Finished }; 713 struct delete_msg_t { inline message; } delete_msg = __base_msg_finished; 714 struct destroy_msg_t { inline message; } destroy_msg = __base_msg_finished; 715 struct finished_msg_t { inline message; } finished_msg = __base_msg_finished; 716 717 allocation receive( actor & this, delete_msg_t & msg ) { return Delete; } 718 allocation receive( actor & this, destroy_msg_t & msg ) { return Destroy; } 719 allocation receive( actor & this, finished_msg_t & msg ) { return Finished; } -
libcfa/src/concurrency/alarm.hfa
r92355883 r2a301ff 10 10 // Created On : Fri Jun 2 11:31:25 2017 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Mon Mar 26 16:25:41 201813 // Update Count : 1 112 // Last Modified On : Wed Aug 30 21:27:40 2023 13 // Update Count : 12 14 14 // 15 15 … … 23 23 #include "time.hfa" 24 24 25 #include "co ntainers/list.hfa"25 #include "collections/list.hfa" 26 26 27 27 struct thread$; -
libcfa/src/concurrency/channel.hfa
r92355883 r2a301ff 68 68 #endif 69 69 }; 70 static inline void ?{}( channel(T) & this, channel(T) this2 ) = void; 71 static inline void ?=?( channel(T) & this, channel(T) this2 ) = void; 70 72 71 73 static inline void ?{}( channel(T) &c, size_t _size ) with(c) { … … 326 328 return retval; 327 329 } 330 static inline void remove( channel(T) & chan ) { T elem = (T)remove( chan ); } 331 332 333 /////////////////////////////////////////////////////////////////////////////////////////// 334 // The following is Go-style operator support for channels 335 /////////////////////////////////////////////////////////////////////////////////////////// 336 337 static inline void ?<<?( channel(T) & chan, T elem ) { insert( chan, elem ); } 338 static inline void ?<<?( T & ret, channel(T) & chan ) { ret = remove( chan ); } 328 339 329 340 /////////////////////////////////////////////////////////////////////////////////////////// … … 340 351 unlock( mutex_lock ); 341 352 342 // only return true when not special OR case , not exceptional calseand status is SAT343 return ( node.extra == 0p || !node.park_counter )? false : *node.clause_status == __SELECT_SAT;353 // only return true when not special OR case and status is SAT 354 return !node.park_counter ? false : *node.clause_status == __SELECT_SAT; 344 355 } 345 356 … … 363 374 // type used by select statement to capture a chan read as the selected operation 364 375 struct chan_read { 365 T &ret;366 channel(T) &chan;376 T * ret; 377 channel(T) * chan; 367 378 }; 368 369 static inline void ?{}( chan_read(T) & cr, channel(T) & chan, T & ret ) { 370 &cr.chan = &chan; 371 &cr.ret = &ret; 372 } 373 static inline chan_read(T) ?<<?( T & ret, channel(T) & chan ) { chan_read(T) cr{ chan, ret }; return cr; } 374 375 static inline void __handle_select_closed_read( chan_read(T) & this, select_node & node ) with(this.chan, this) { 376 __closed_remove( chan, ret ); 379 __CFA_SELECT_GET_TYPE( chan_read(T) ); 380 381 static inline void ?{}( chan_read(T) & cr, channel(T) * chan, T * ret ) { 382 cr.chan = chan; 383 cr.ret = ret; 384 } 385 static inline chan_read(T) ?<<?( T & ret, channel(T) & chan ) { chan_read(T) cr{ &chan, &ret }; return cr; } 386 387 static inline void __handle_select_closed_read( chan_read(T) & this, select_node & node ) with(*this.chan, this) { 388 __closed_remove( *chan, *ret ); 377 389 // if we get here then the insert succeeded 378 390 __make_select_node_available( node ); 379 391 } 380 392 381 static inline bool register_select( chan_read(T) & this, select_node & node ) with( this.chan, this) {382 lock( mutex_lock ); 383 node.extra = &ret; // set .extra so that if it == 0p later in on_selected it is due to channel close393 static inline bool register_select( chan_read(T) & this, select_node & node ) with(*this.chan, this) { 394 lock( mutex_lock ); 395 node.extra = ret; // set .extra so that if it == 0p later in on_selected it is due to channel close 384 396 385 397 #ifdef CHAN_STATS … … 396 408 397 409 if ( __handle_pending( prods, node ) ) { 398 __prods_handoff( chan,ret );410 __prods_handoff( *chan, *ret ); 399 411 __make_select_node_sat( node ); // need to to mark SAT now that we know operation is done or else threads could get stuck in __mark_select_node 400 412 unlock( mutex_lock ); … … 422 434 ZeroSize: if ( size == 0 && !prods`isEmpty ) { 423 435 if ( !__handle_waituntil_OR( prods ) ) break ZeroSize; 424 __prods_handoff( chan,ret );436 __prods_handoff( *chan, *ret ); 425 437 __set_avail_then_unlock( node, mutex_lock ); 426 438 return true; … … 439 451 440 452 // Remove from buffer 441 __do_remove( chan,ret );453 __do_remove( *chan, *ret ); 442 454 __set_avail_then_unlock( node, mutex_lock ); 443 455 return true; 444 456 } 445 static inline bool unregister_select( chan_read(T) & this, select_node & node ) { return unregister_chan( this.chan, node ); } 446 static inline void on_selected( chan_read(T) & this, select_node & node ) with(this) { 447 if ( node.extra == 0p ) // check if woken up due to closed channel 448 __closed_remove( chan, ret ); 457 static inline bool unregister_select( chan_read(T) & this, select_node & node ) { return unregister_chan( *this.chan, node ); } 458 static inline bool on_selected( chan_read(T) & this, select_node & node ) with(this) { 459 if ( unlikely(node.extra == 0p) ) { 460 if ( !exception_in_flight() ) __closed_remove( *chan, *ret ); // check if woken up due to closed channel 461 else return false; 462 } 449 463 // This is only reachable if not closed or closed exception was handled 450 } 464 return true; 465 } 466 467 // type used by select statement to capture a chan read as the selected operation that doesn't have a param to read to 468 struct chan_read_no_ret { 469 T retval; 470 chan_read( T ) c_read; 471 }; 472 __CFA_SELECT_GET_TYPE( chan_read_no_ret(T) ); 473 474 static inline void ?{}( chan_read_no_ret(T) & this, channel(T) & chan ) { 475 this.c_read{ &chan, &this.retval }; 476 } 477 478 static inline chan_read_no_ret(T) remove( channel(T) & chan ) { chan_read_no_ret(T) c_read{ chan }; return c_read; } 479 static inline bool register_select( chan_read_no_ret(T) & this, select_node & node ) { 480 this.c_read.ret = &this.retval; 481 return register_select( this.c_read, node ); 482 } 483 static inline bool unregister_select( chan_read_no_ret(T) & this, select_node & node ) { return unregister_select( this.c_read, node ); } 484 static inline bool on_selected( chan_read_no_ret(T) & this, select_node & node ) { return on_selected( this.c_read, node ); } 451 485 452 486 // type used by select statement to capture a chan write as the selected operation 453 487 struct chan_write { 454 488 T elem; 455 channel(T) &chan;489 channel(T) * chan; 456 490 }; 457 458 static inline void ?{}( chan_write(T) & cw, channel(T) & chan, T elem ) { 459 &cw.chan = &chan; 491 __CFA_SELECT_GET_TYPE( chan_write(T) ); 492 493 static inline void ?{}( chan_write(T) & cw, channel(T) * chan, T elem ) { 494 cw.chan = chan; 460 495 memcpy( (void *)&cw.elem, (void *)&elem, sizeof(T) ); 461 496 } 462 static inline chan_write(T) ?>>?( T elem, channel(T) & chan ) { chan_write(T) cw{ chan, elem }; return cw; } 463 464 static inline void __handle_select_closed_write( chan_write(T) & this, select_node & node ) with(this.chan, this) { 465 __closed_insert( chan, elem ); 497 static inline chan_write(T) ?<<?( channel(T) & chan, T elem ) { chan_write(T) cw{ &chan, elem }; return cw; } 498 static inline chan_write(T) insert( T elem, channel(T) & chan) { chan_write(T) cw{ &chan, elem }; return cw; } 499 500 static inline void __handle_select_closed_write( chan_write(T) & this, select_node & node ) with(*this.chan, this) { 501 __closed_insert( *chan, elem ); 466 502 // if we get here then the insert succeeded 467 503 __make_select_node_available( node ); 468 504 } 469 505 470 static inline bool register_select( chan_write(T) & this, select_node & node ) with( this.chan, this) {506 static inline bool register_select( chan_write(T) & this, select_node & node ) with(*this.chan, this) { 471 507 lock( mutex_lock ); 472 508 node.extra = &elem; // set .extra so that if it == 0p later in on_selected it is due to channel close … … 486 522 487 523 if ( __handle_pending( cons, node ) ) { 488 __cons_handoff( chan, elem );524 __cons_handoff( *chan, elem ); 489 525 __make_select_node_sat( node ); // need to to mark SAT now that we know operation is done or else threads could get stuck in __mark_select_node 490 526 unlock( mutex_lock ); … … 513 549 ConsEmpty: if ( !cons`isEmpty ) { 514 550 if ( !__handle_waituntil_OR( cons ) ) break ConsEmpty; 515 __cons_handoff( chan, elem );551 __cons_handoff( *chan, elem ); 516 552 __set_avail_then_unlock( node, mutex_lock ); 517 553 return true; … … 530 566 531 567 // otherwise carry out write either via normal insert 532 __buf_insert( chan, elem );568 __buf_insert( *chan, elem ); 533 569 __set_avail_then_unlock( node, mutex_lock ); 534 570 return true; 535 571 } 536 static inline bool unregister_select( chan_write(T) & this, select_node & node ) { return unregister_chan( this.chan, node ); } 537 538 static inline void on_selected( chan_write(T) & this, select_node & node ) with(this) { 539 if ( node.extra == 0p ) // check if woken up due to closed channel 540 __closed_insert( chan, elem ); 541 572 static inline bool unregister_select( chan_write(T) & this, select_node & node ) { return unregister_chan( *this.chan, node ); } 573 574 static inline bool on_selected( chan_write(T) & this, select_node & node ) with(this) { 575 if ( unlikely(node.extra == 0p) ) { 576 if ( !exception_in_flight() ) __closed_insert( *chan, elem ); // check if woken up due to closed channel 577 else return false; 578 } 542 579 // This is only reachable if not closed or closed exception was handled 580 return true; 543 581 } 544 582 -
libcfa/src/concurrency/coroutine.cfa
r92355883 r2a301ff 28 28 #include "kernel/private.hfa" 29 29 #include "exception.hfa" 30 #include "exception.h" 30 31 #include "math.hfa" 31 32 … … 77 78 free( desc->cancellation ); 78 79 desc->cancellation = 0p; 80 } 81 82 // helper for popping from coroutine's ehm buffer 83 inline nonlocal_exception * pop_ehm_head( coroutine$ * this ) { 84 lock( this->ehm_state.buffer_lock __cfaabi_dbg_ctx2 ); 85 nonlocal_exception * nl_ex = pop_head( this->ehm_state.ehm_buffer ); 86 unlock( this->ehm_state.buffer_lock ); 87 return nl_ex; 79 88 } 80 89 … … 121 130 last = 0p; 122 131 cancellation = 0p; 132 ehm_state.ehm_buffer{}; 133 ehm_state.buffer_lock{}; 134 ehm_state.ehm_enabled = false; 123 135 } 124 136 125 137 void ^?{}(coroutine$& this) libcfa_public { 138 // handle any leftover pending non-local exceptions 139 nonlocal_exception * nl_ex = pop_ehm_head( &this ); 140 unsigned unhandled_ex = 0; 141 142 // if any leftover exceptions handle 143 while ( nl_ex != 0p ){ 144 unhandled_ex++; 145 free( nl_ex->the_exception ); 146 free( nl_ex ); 147 nl_ex = pop_ehm_head( &this ); 148 } 149 150 #ifdef __CFA_DEBUG__ 151 if ( unhandled_ex > 0 ) 152 printf( "Warning: Coroutine %p exited with %u pending nonlocal exceptions.\n", &this, unhandled_ex ); 153 #endif 154 126 155 if(this.state != Halted && this.state != Start && this.state != Primed) { 127 156 coroutine$ * src = active_coroutine(); … … 283 312 } 284 313 314 315 //////////////////////////////////////////////////////////////////////////////////////////////////// 316 // non local ehm routines 317 318 void defaultResumeAtHandler( exception_t * except ) { 319 __cfaehm_allocate_exception( except ); 320 free( except ); 321 __cfaehm_begin_unwind( (void(*)(exception_t *))defaultTerminationHandler ); 322 } 323 324 bool poll( coroutine$ * cor ) libcfa_public { 325 nonlocal_exception * nl_ex = pop_ehm_head( cor ); 326 327 // if no exceptions return false 328 if ( nl_ex == 0p ) return false; 329 330 // otherwise loop and throwResume all pending exceptions 331 while ( nl_ex != 0p ){ 332 exception_t * ex = nl_ex->the_exception; 333 free( nl_ex ); 334 __cfaehm_throw_resume( ex, defaultResumeAtHandler ); 335 336 // only reached if resumption handled. other dealloc handled in defaultResumeAtHandler 337 free( ex ); 338 nl_ex = pop_ehm_head( cor ); 339 } 340 341 return true; 342 } 343 344 bool poll() libcfa_public { return poll( active_coroutine() ); } 345 coroutine$ * resumer() libcfa_public { return active_coroutine()->last; } 346 347 // user facing ehm operations 348 forall(T & | is_coroutine(T)) { 349 // enable/disable non-local exceptions 350 void enable_ehm( T & cor ) libcfa_public { get_coroutine( cor )->ehm_state.ehm_enabled = true; } 351 void disable_ehm( T & cor ) libcfa_public { get_coroutine( cor )->ehm_state.ehm_enabled = false; } 352 353 // poll for non-local exceptions 354 bool poll( T & cor ) libcfa_public { return poll( get_coroutine( cor ) ); } 355 356 // poll iff nonlocal ehm is enabled 357 bool checked_poll( T & cor ) libcfa_public { return get_coroutine( cor )->ehm_state.ehm_enabled ? poll( cor ) : false; } 358 359 coroutine$ * resumer( T & cor ) libcfa_public { return get_coroutine( cor )->last; } 360 } 361 362 // resume non local exception at receiver (i.e. enqueue in ehm buffer) 363 forall(exceptT *, T & | ehm_resume_at( exceptT, T )) 364 void resumeAt( T & receiver, exceptT & ex ) libcfa_public { 365 coroutine$ * cor = get_coroutine( receiver ); 366 nonlocal_exception * nl_ex = alloc(); 367 exceptT * ex_copy = alloc(); 368 memcpy( ex_copy, &ex, sizeof(exceptT) ); 369 (*nl_ex){ (exception_t *)ex_copy }; 370 lock( cor->ehm_state.buffer_lock __cfaabi_dbg_ctx2 ); 371 append( cor->ehm_state.ehm_buffer, nl_ex ); 372 unlock( cor->ehm_state.buffer_lock ); 373 } 374 375 forall(exceptT * | { void $throwResume(exceptT &); }) 376 void resumeAt( coroutine$ * receiver, exceptT & ex ) libcfa_public { 377 nonlocal_exception * nl_ex = alloc(); 378 exceptT * ex_copy = alloc(); 379 memcpy( ex_copy, &ex, sizeof(exceptT) ); 380 (*nl_ex){ (exception_t *)ex_copy }; 381 lock( receiver->ehm_state.buffer_lock __cfaabi_dbg_ctx2 ); 382 append( receiver->ehm_state.ehm_buffer, nl_ex ); 383 unlock( receiver->ehm_state.buffer_lock ); 384 } 385 285 386 // Local Variables: // 286 387 // mode: c // -
libcfa/src/concurrency/coroutine.hfa
r92355883 r2a301ff 19 19 #include "invoke.h" 20 20 #include "../exception.hfa" 21 22 //----------------------------------------------------------------------------- 23 // Type used to store and queue nonlocal exceptions on coroutines 24 struct nonlocal_exception { 25 exception_t * the_exception; 26 nonlocal_exception * next; 27 }; 28 static inline void ?{} ( nonlocal_exception & this, exception_t * ex ) with(this) { 29 the_exception = ex; 30 next = 0p; 31 } 32 33 static inline nonlocal_exception *& get_next( nonlocal_exception & this ) __attribute__((const)) { 34 return this.next; 35 } 21 36 22 37 //----------------------------------------------------------------------------- … … 203 218 } 204 219 220 // non local ehm and coroutine utility routines 221 bool poll( coroutine$ * cor ); 222 bool poll(); 223 coroutine$ * resumer(); 224 225 forall(T & | is_coroutine(T)) { 226 void enable_ehm( T & cor ); 227 void disable_ehm( T & cor ); 228 bool poll( T & cor ); 229 bool checked_poll( T & cor ); 230 coroutine$ * resumer( T & cor ); 231 } 232 233 // trait for exceptions able to be resumed at another coroutine 234 forall(exceptT *, T & | is_coroutine(T)) 235 trait ehm_resume_at { void $throwResume(exceptT &); }; 236 237 // general resumeAt 238 forall(exceptT *, T & | ehm_resume_at( exceptT, T )) 239 void resumeAt( T & receiver, exceptT & ex ); 240 241 // resumeAt for underlying coroutine$ type 242 forall(exceptT * | { void $throwResume(exceptT &); }) 243 void resumeAt( coroutine$ * receiver, exceptT & ex ); 244 205 245 // Local Variables: // 206 246 // mode: c // -
libcfa/src/concurrency/future.hfa
r92355883 r2a301ff 39 39 futex_mutex lock; 40 40 }; 41 __CFA_SELECT_GET_TYPE( future(T) ); 41 42 42 43 struct future_node { … … 180 181 } 181 182 182 void on_selected( future(T) & this, select_node & node ) {}183 bool on_selected( future(T) & this, select_node & node ) { return true; } 183 184 } 184 185 } -
libcfa/src/concurrency/invoke.h
r92355883 r2a301ff 10 10 // Created On : Tue Jan 17 12:27:26 2016 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Tue Mar 14 13:39:31 202313 // Update Count : 5912 // Last Modified On : Wed Aug 30 21:27:51 2023 13 // Update Count : 60 14 14 // 15 15 16 16 // No not use #pragma once was this file is included twice in some places. It has its own guard system. 17 17 18 #include "bits/co ntainers.hfa"18 #include "bits/collections.hfa" 19 19 #include "bits/defs.hfa" 20 20 #include "bits/locks.hfa" … … 23 23 24 24 #ifdef __cforall 25 #include "co ntainers/list.hfa"25 #include "collections/list.hfa" 26 26 extern "C" { 27 27 #endif … … 74 74 }; 75 75 76 struct nonlocal_ehm { 77 // list of pending nonlocal exceptions 78 __queue_t(struct nonlocal_exception) ehm_buffer; 79 80 // lock to protect the buffer 81 struct __spinlock_t buffer_lock; 82 83 // enable/disabled flag 84 bool ehm_enabled; 85 }; 86 76 87 enum __Coroutine_State { Halted, Start, Primed, Blocked, Ready, Active, Cancelled, Halting }; 77 88 … … 98 109 struct _Unwind_Exception * cancellation; 99 110 111 // Non-local exception handling information 112 struct nonlocal_ehm ehm_state; 100 113 }; 101 114 // Wrapper for gdb … … 242 255 #ifdef __cforall 243 256 extern "Cforall" { 257 static inline bool exception_in_flight() { 258 return __get_stack( &active_thread()->self_cor )->exception_context.current_exception != 0p; 259 } 260 244 261 static inline thread$ * volatile & ?`next ( thread$ * this ) { 245 262 return this->user_link.next; -
libcfa/src/concurrency/iofwd.hfa
r92355883 r2a301ff 10 10 // Created On : Thu Apr 23 17:31:00 2020 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Mon Mar 13 23:54:57202313 // Update Count : 112 // Last Modified On : Fri Jul 21 21:36:01 2023 13 // Update Count : 3 14 14 // 15 15 … … 18 18 #include <unistd.h> 19 19 #include <sys/socket.h> 20 #include <string.h> // memset 20 21 21 22 extern "C" { … … 151 152 #if CFA_HAVE_LINUX_IO_URING_H 152 153 static inline void zero_sqe(struct io_uring_sqe * sqe) { 153 sqe->flags = 0; 154 sqe->ioprio = 0; 155 sqe->fd = 0; 156 sqe->off = 0; 157 sqe->addr = 0; 158 sqe->len = 0; 159 sqe->fsync_flags = 0; 160 sqe->__pad2[0] = 0; 161 sqe->__pad2[1] = 0; 162 sqe->__pad2[2] = 0; 163 sqe->fd = 0; 164 sqe->off = 0; 165 sqe->addr = 0; 166 sqe->len = 0; 154 memset( sqe, 0, sizeof( struct io_uring_sqe ) ); 167 155 } 168 156 #endif -
libcfa/src/concurrency/kernel.cfa
r92355883 r2a301ff 569 569 returnToKernel(); 570 570 __enable_interrupts_checked(); 571 572 571 } 573 572 -
libcfa/src/concurrency/kernel.hfa
r92355883 r2a301ff 10 10 // Created On : Tue Jan 17 12:27:26 2017 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Tue Feb 4 12:29:26 202013 // Update Count : 2 212 // Last Modified On : Wed Aug 30 21:28:46 2023 13 // Update Count : 23 14 14 // 15 15 … … 20 20 #include "coroutine.hfa" 21 21 22 #include "co ntainers/list.hfa"22 #include "collections/list.hfa" 23 23 24 24 extern "C" { -
libcfa/src/concurrency/kernel/startup.cfa
r92355883 r2a301ff 487 487 last = 0p; 488 488 cancellation = 0p; 489 ehm_state.ehm_buffer{}; 490 ehm_state.buffer_lock{}; 491 ehm_state.ehm_enabled = false; 489 492 } 490 493 -
libcfa/src/concurrency/locks.cfa
r92355883 r2a301ff 239 239 } 240 240 241 void on_selected( blocking_lock & this, select_node & node ) {}241 bool on_selected( blocking_lock & this, select_node & node ) { return true; } 242 242 243 243 //----------------------------------------------------------------------------- -
libcfa/src/concurrency/locks.hfa
r92355883 r2a301ff 21 21 22 22 #include "bits/weakso_locks.hfa" 23 #include "co ntainers/lockfree.hfa"24 #include "co ntainers/list.hfa"23 #include "collections/lockfree.hfa" 24 #include "collections/list.hfa" 25 25 26 26 #include "limits.hfa" … … 112 112 static inline bool register_select( single_acquisition_lock & this, select_node & node ) { return register_select( (blocking_lock &)this, node ); } 113 113 static inline bool unregister_select( single_acquisition_lock & this, select_node & node ) { return unregister_select( (blocking_lock &)this, node ); } 114 static inline void on_selected( single_acquisition_lock & this, select_node & node ) { on_selected( (blocking_lock &)this, node ); } 114 static inline bool on_selected( single_acquisition_lock & this, select_node & node ) { return on_selected( (blocking_lock &)this, node ); } 115 __CFA_SELECT_GET_TYPE( single_acquisition_lock ); 115 116 116 117 //---------- … … 129 130 static inline bool register_select( owner_lock & this, select_node & node ) { return register_select( (blocking_lock &)this, node ); } 130 131 static inline bool unregister_select( owner_lock & this, select_node & node ) { return unregister_select( (blocking_lock &)this, node ); } 131 static inline void on_selected( owner_lock & this, select_node & node ) { on_selected( (blocking_lock &)this, node ); } 132 static inline bool on_selected( owner_lock & this, select_node & node ) { return on_selected( (blocking_lock &)this, node ); } 133 __CFA_SELECT_GET_TYPE( owner_lock ); 132 134 133 135 //----------------------------------------------------------------------------- … … 138 140 }; 139 141 140 static inline void ?{}( mcs_node & this) { this.next = 0p; }142 static inline void ?{}( mcs_node & this ) { this.next = 0p; } 141 143 142 144 static inline mcs_node * volatile & ?`next ( mcs_node * node ) { … … 148 150 }; 149 151 150 static inline void lock( mcs_lock & l, mcs_node & n) {152 static inline void lock( mcs_lock & l, mcs_node & n ) { 151 153 if(push(l.queue, &n)) 152 154 wait(n.sem); … … 172 174 }; 173 175 174 static inline void ?{}( mcs_spin_node & this) { this.next = 0p; this.locked = true; }176 static inline void ?{}( mcs_spin_node & this ) { this.next = 0p; this.locked = true; } 175 177 176 178 struct mcs_spin_lock { … … 178 180 }; 179 181 180 static inline void lock( mcs_spin_lock & l, mcs_spin_node & n) {182 static inline void lock( mcs_spin_lock & l, mcs_spin_node & n ) { 181 183 n.locked = true; 182 184 mcs_spin_node * prev = __atomic_exchange_n(&l.queue.tail, &n, __ATOMIC_SEQ_CST); … … 271 273 }; 272 274 static inline void ?{}( go_mutex & this ) with(this) { val = 0; } 273 // static inline void ?{}( go_mutex & this, go_mutex this2 ) = void; // these don't compile correctly at the moment so they should be omitted 274 //static inline void ?=?( go_mutex & this, go_mutex this2 ) = void;275 static inline void ?{}( go_mutex & this, go_mutex this2 ) = void; 276 static inline void ?=?( go_mutex & this, go_mutex this2 ) = void; 275 277 276 278 static inline bool internal_try_lock(go_mutex & this, int & compare_val, int new_val ) with(this) { … … 619 621 } 620 622 621 static inline void on_selected( simple_owner_lock & this, select_node & node ) {}622 623 static inline bool on_selected( simple_owner_lock & this, select_node & node ) { return true; } 624 __CFA_SELECT_GET_TYPE( simple_owner_lock ); 623 625 624 626 //----------------------------------------------------------------------------- -
libcfa/src/concurrency/once.hfa
r92355883 r2a301ff 16 16 #pragma once 17 17 18 #include "co ntainers/lockfree.hfa"18 #include "collections/lockfree.hfa" 19 19 #include "kernel/fwd.hfa" 20 20 -
libcfa/src/concurrency/select.cfa
r92355883 r2a301ff 49 49 return false; 50 50 } 51 void on_selected( select_timeout_node & this, select_node & node ) {}51 bool on_selected( select_timeout_node & this, select_node & node ) { return true; } 52 52 53 53 // Gateway routine to wait on duration -
libcfa/src/concurrency/select.hfa
r92355883 r2a301ff 17 17 #pragma once 18 18 19 #include "co ntainers/list.hfa"19 #include "collections/list.hfa" 20 20 #include "alarm.hfa" 21 21 #include "kernel.hfa" … … 94 94 95 95 // This routine is run on the selecting thread prior to executing the statement corresponding to the select_node 96 // passed as an arg to this routine 97 // If on_selected returns false, the statement is not run, if it returns true it is run. 98 void on_selected( T &, select_node & ); 96 // passed as an arg to this routine. If true is returned proceed as normal, if false is returned the statement is skipped 97 bool on_selected( T &, select_node & ); 99 98 }; 99 // Used inside the compiler to allow for overloading on return type for operations such as '?<<?' for channels 100 // YOU MUST USE THIS MACRO OR INCLUDE AN EQUIVALENT DECL FOR YOUR TYPE TO SUPPORT WAITUNTIL 101 #define __CFA_SELECT_GET_TYPE( typename ) typename __CFA_select_get_type( typename __CFA_t ) 102 100 103 101 104 //============================================================================================= … … 208 211 bool register_select( select_timeout_node & this, select_node & node ); 209 212 bool unregister_select( select_timeout_node & this, select_node & node ); 210 void on_selected( select_timeout_node & this, select_node & node ); 213 bool on_selected( select_timeout_node & this, select_node & node ); 214 select_timeout_node __CFA_select_get_type( select_timeout_node this ); 211 215 212 216 // Gateway routines to waituntil on duration 213 217 select_timeout_node timeout( Duration duration ); 214 218 select_timeout_node sleep( Duration duration ); 219 -
libcfa/src/concurrency/stats.cfa
r92355883 r2a301ff 11 11 #if !defined(__CFA_NO_STATISTICS__) 12 12 void __init_stats( struct __stats_t * stats ) { 13 stats->ready.push.local.attempt = 0; 14 stats->ready.push.local.success = 0; 15 stats->ready.push.share.attempt = 0; 16 stats->ready.push.share.success = 0; 17 stats->ready.push.extrn.attempt = 0; 18 stats->ready.push.extrn.success = 0; 19 stats->ready.pop.local .attempt = 0; 20 stats->ready.pop.local .success = 0; 21 stats->ready.pop.help .attempt = 0; 22 stats->ready.pop.help .success = 0; 23 stats->ready.pop.steal .attempt = 0; 24 stats->ready.pop.steal .success = 0; 25 stats->ready.pop.search.attempt = 0; 26 stats->ready.pop.search.success = 0; 27 stats->ready.threads.migration = 0; 28 stats->ready.threads.extunpark = 0; 29 stats->ready.threads.threads = 0; 30 stats->ready.threads.cthreads = 0; 31 stats->ready.threads.preempt.yield = 0; 32 stats->ready.threads.preempt.rllfwd = 0; 33 stats->ready.sleep.halts = 0; 34 stats->ready.sleep.cancels = 0; 35 stats->ready.sleep.early = 0; 36 stats->ready.sleep.wakes = 0; 37 stats->ready.sleep.seen = 0; 38 stats->ready.sleep.exits = 0; 13 memset( &stats->ready, 0, sizeof( stats->ready ) ); 39 14 40 15 #if defined(CFA_HAVE_LINUX_IO_URING_H) 41 stats->io.alloc.fast = 0; 42 stats->io.alloc.slow = 0; 43 stats->io.alloc.fail = 0; 44 stats->io.alloc.revoke = 0; 45 stats->io.alloc.block = 0; 46 stats->io.submit.fast = 0; 47 stats->io.submit.slow = 0; 48 stats->io.submit.eagr = 0; 49 stats->io.submit.nblk = 0; 50 stats->io.submit.extr = 0; 51 stats->io.flush.external = 0; 52 stats->io.flush.signal = 0; 53 stats->io.flush.dirty = 0; 54 stats->io.flush.full = 0; 55 stats->io.flush.idle = 0; 56 stats->io.flush.eager = 0; 57 stats->io.calls.flush = 0; 58 stats->io.calls.submitted = 0; 59 stats->io.calls.drain = 0; 60 stats->io.calls.completed = 0; 61 stats->io.calls.locked = 0; 62 stats->io.calls.helped = 0; 63 stats->io.calls.errors.busy = 0; 64 stats->io.ops.sockread = 0; 65 stats->io.ops.epllread = 0; 66 stats->io.ops.sockwrite = 0; 67 stats->io.ops.epllwrite = 0; 16 memset( &stats->io, 0, sizeof( stats->io ) ); 68 17 #endif 69 18 -
libcfa/src/exception.c
r92355883 r2a301ff 9 9 // Author : Andrew Beach 10 10 // Created On : Mon Jun 26 15:13:00 2017 11 // Last Modified By : Andrew Beach12 // Last Modified On : Wed Feb 24 13:40:00 202113 // Update Count : 3611 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Thu Aug 10 16:45:22 2023 13 // Update Count : 69 14 14 // 15 15 … … 27 27 #include "stdhdr/assert.h" 28 28 #include "virtual.h" 29 30 extern void __cabi_abort( const char fmt[], ... ); 29 31 30 32 #pragma GCC visibility push(default) … … 123 125 124 126 // Creates a copy of the indicated exception and sets current_exception to it. 125 staticvoid __cfaehm_allocate_exception( exception_t * except ) {127 void __cfaehm_allocate_exception( exception_t * except ) { 126 128 struct exception_context_t * context = this_exception_context(); 127 129 … … 192 194 193 195 if ( actions & _UA_END_OF_STACK ) { 194 abort(); 196 __cabi_abort( 197 "Propagation failed to find a matching handler.\n" 198 "Possible cause is a missing try block with appropriate catch clause for specified exception type.\n" 199 "Last exception name or message: %s.\n", 200 NODE_TO_EXCEPT( UNWIND_TO_NODE( unwind_exception ) )-> 201 virtual_table->msg( NODE_TO_EXCEPT( UNWIND_TO_NODE( unwind_exception ) ) ) 202 ); 195 203 } else { 196 204 return _URC_NO_REASON; … … 209 217 struct exception_context_t * context = this_exception_context(); 210 218 struct __cfaehm_node * node = EXCEPT_TO_NODE(context->current_exception); 211 212 // Preform clean-up of any extra active exceptions.213 while ( node->next ) {214 struct __cfaehm_node * to_free = node->next;215 node->next = to_free->next;216 exception_t * except = NODE_TO_EXCEPT( to_free );217 except->virtual_table->free( except );218 free( to_free );219 }220 219 221 220 _Unwind_Reason_Code ret; … … 239 238 240 239 // The exception that is being thrown must already be stored. 241 staticvoid __cfaehm_begin_unwind(void(*defaultHandler)(exception_t *)) {240 void __cfaehm_begin_unwind(void(*defaultHandler)(exception_t *)) { 242 241 struct exception_context_t * context = this_exception_context(); 243 242 if ( NULL == context->current_exception ) { … … 568 567 " .hidden CFA.ref.__gcfa_personality_v0\n" 569 568 " .weak CFA.ref.__gcfa_personality_v0\n" 570 // No clue what this does specifically571 " .section .data.rel.local.CFA.ref.__gcfa_personality_v0,\"awG\",@progbits,CFA.ref.__gcfa_personality_v0,comdat\n"572 569 #if defined( __x86_64 ) || defined( __i386 ) 573 570 " .align 8\n" -
libcfa/src/exception.h
r92355883 r2a301ff 50 50 void __cfaehm_rethrow_terminate() __attribute__((noreturn)); 51 51 void __cfaehm_throw_resume(exception_t * except, void (*)(exception_t *)); 52 53 // Used in non-local ehm (see coroutine.cfa) 54 void __cfaehm_allocate_exception( exception_t * except ); 55 void __cfaehm_begin_unwind(void(*defaultHandler)(exception_t *)); 56 52 57 53 58 // Function catches termination exceptions. -
libcfa/src/executor.baseline.txt
r92355883 r2a301ff 5 5 6 6 #include <thread.hfa> 7 #include <co ntainers/list.hfa>7 #include <collections/list.hfa> 8 8 9 9 forall( T & | $dlistable(T, T) ) { -
libcfa/src/executor.cfa
r92355883 r2a301ff 5 5 6 6 #include <thread.hfa> 7 #include <co ntainers/list.hfa>7 #include <collections/list.hfa> 8 8 9 9 forall( T &, TLink& = dlink(T) | embedded(T, TLink, dlink(T)) ) { -
libcfa/src/fstream.cfa
r92355883 r2a301ff 10 10 // Created On : Wed May 27 17:56:53 2015 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Sat Jun 17 08:51:12202313 // Update Count : 5 2812 // Last Modified On : Fri Aug 18 10:41:17 2023 13 // Update Count : 541 14 14 // 15 15 … … 24 24 25 25 #pragma GCC visibility push(default) 26 26 27 27 28 // *********************************** ofstream *********************************** … … 43 44 } // ?{} 44 45 46 inline bool getNL$( ofstream & os ) { return os.sawNL$; } 47 inline bool setNL$( ofstream & os, bool state ) { bool temp = os.sawNL$; os.sawNL$ = state; return temp; } 48 inline bool getANL$( ofstream & os ) { return os.nlOnOff$; } 49 inline bool setANL$( ofstream & os, bool state ) { bool temp = os.nlOnOff$; os.nlOnOff$ = state; return temp; } 50 45 51 inline bool sepPrt$( ofstream & os ) { setNL$( os, false ); return os.sepOnOff$; } 46 52 inline void sepReset$( ofstream & os ) { os.sepOnOff$ = os.sepDefault$; } … … 48 54 inline const char * sepGetCur$( ofstream & os ) { return os.sepCur$; } 49 55 inline void sepSetCur$( ofstream & os, const char sepCur[] ) { os.sepCur$ = sepCur; } 50 inline bool getNL$( ofstream & os ) { return os.sawNL$; } 51 inline void setNL$( ofstream & os, bool state ) { os.sawNL$ = state; } 52 inline bool getANL$( ofstream & os ) { return os.nlOnOff$; } 56 53 57 inline bool getPrt$( ofstream & os ) { return os.prt$; } 54 inline void setPrt$( ofstream & os, bool state ) { os.prt$ = state; }58 inline bool setPrt$( ofstream & os, bool state ) { bool temp = os.prt$; os.prt$ = state; return temp; } 55 59 56 60 inline void lock( ofstream & os ) with( os ) { lock( os.lock$ ); } … … 63 67 void ^?{}( ofstream & os ) { close( os ); } 64 68 65 void sepOn( ofstream & os ) { os.sepOnOff$ = ! getNL$( os ); } 66 void sepOff( ofstream & os ) { os.sepOnOff$ = false; } 67 68 bool sepDisable( ofstream & os ) { 69 void nlOn( ofstream & os ) { os.nlOnOff$ = true; } 70 void nlOff( ofstream & os ) { os.nlOnOff$ = false; } 71 72 void sep( ofstream & os ) { os.sepOnOff$ = ! getNL$( os ); } 73 void nosep( ofstream & os ) { os.sepOnOff$ = false; } 74 75 bool sepOn( ofstream & os ) { 76 bool temp = os.sepDefault$; 77 os.sepDefault$ = true; 78 if ( os.sepOnOff$ ) sepReset$( os ); // start of line ? 79 return temp; 80 } // sepOn 81 82 bool sepOff( ofstream & os ) { 69 83 bool temp = os.sepDefault$; 70 84 os.sepDefault$ = false; 71 85 sepReset$( os ); 72 86 return temp; 73 } // sepDisable 74 75 bool sepEnable( ofstream & os ) { 76 bool temp = os.sepDefault$; 77 os.sepDefault$ = true; 78 if ( os.sepOnOff$ ) sepReset$( os ); // start of line ? 79 return temp; 80 } // sepEnable 81 82 void nlOn( ofstream & os ) { os.nlOnOff$ = true; } 83 void nlOff( ofstream & os ) { os.nlOnOff$ = false; } 87 } // sepOff 84 88 85 89 const char * sepGet( ofstream & os ) { return os.separator$; } … … 209 213 210 214 bool getANL$( ifstream & os ) { return os.nlOnOff$; } 215 bool setANL$( ifstream & os, bool state ) { bool temp = os.nlOnOff$; os.nlOnOff$ = state; return temp; } 211 216 212 217 inline void lock( ifstream & os ) with( os ) { lock( os.lock$ ); } -
libcfa/src/fstream.hfa
r92355883 r2a301ff 10 10 // Created On : Wed May 27 17:56:53 2015 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Mon Jun 5 22:00:20202313 // Update Count : 2 4612 // Last Modified On : Fri Aug 18 10:41:15 2023 13 // Update Count : 258 14 14 // 15 15 … … 34 34 char separator$[ofstream_sepSize]; 35 35 char tupleSeparator$[ofstream_sepSize]; 36 multiple_acquisition_lock lock$; 36 multiple_acquisition_lock lock$; // used by trait is_lock for mutex statement 37 37 }; // ofstream 38 38 … … 40 40 41 41 // private 42 bool getNL$( ofstream & ); 43 bool setNL$( ofstream &, bool ); 44 bool getANL$( ofstream & ); 45 bool setANL$( ofstream &, bool ); 46 42 47 bool sepPrt$( ofstream & ); 43 48 void sepReset$( ofstream & ); … … 45 50 const char * sepGetCur$( ofstream & ); 46 51 void sepSetCur$( ofstream &, const char [] ); 47 bool getNL$( ofstream & ); 48 void setNL$( ofstream &, bool ); 49 bool getANL$( ofstream & ); 52 50 53 bool getPrt$( ofstream & ); 51 voidsetPrt$( ofstream &, bool );54 bool setPrt$( ofstream &, bool ); 52 55 53 56 void lock( ofstream & ); … … 55 58 56 59 // public 57 void sepOn( ofstream & );58 void sepOff( ofstream & );59 bool sepDisable( ofstream & );60 bool sepEnable( ofstream & );61 60 void nlOn( ofstream & ); 62 61 void nlOff( ofstream & ); 63 62 63 void sep( ofstream & ); 64 void nosep( ofstream & ); 65 bool sepOn( ofstream & ); 66 bool sepOff( ofstream & ); 64 67 const char * sepGet( ofstream & ); 65 68 void sepSet( ofstream &, const char [] ); … … 99 102 void * file$; 100 103 bool nlOnOff$; 101 multiple_acquisition_lock lock$; 104 multiple_acquisition_lock lock$; // used by trait is_lock for mutex statement 102 105 }; // ifstream 103 106 … … 106 109 // private 107 110 bool getANL$( ifstream & ); 111 bool setANL$( ifstream &, bool ); 108 112 109 113 void lock( ifstream & ); -
libcfa/src/gmp.hfa
r92355883 r2a301ff 10 10 // Created On : Tue Apr 19 08:43:43 2016 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Tue Apr 20 20:59:21 202113 // Update Count : 3 212 // Last Modified On : Tue Jul 18 11:04:54 2023 13 // Update Count : 35 14 14 // 15 15 … … 265 265 if ( sepPrt$( os ) ) fmt( os, "%s", sepGetCur$( os ) ); 266 266 gmp_printf( "%Zd", mp.mpz ); 267 sep On( os );267 sep( os ); 268 268 return os; 269 269 } // ?|? 270 271 void ?|?( ostype & os, Int mp ) { 272 (ostype)(os | mp); ends( os ); 273 } // ?|? 270 OSTYPE_VOID_IMPL( Int ) 274 271 } // distribution 275 272 } // distribution -
libcfa/src/heap.cfa
r92355883 r2a301ff 10 10 // Created On : Tue Dec 19 21:58:35 2017 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Fri Dec 30 08:37:37 202213 // Update Count : 16 0512 // Last Modified On : Wed Aug 2 18:48:30 2023 13 // Update Count : 1614 14 14 // 15 15 … … 369 369 static __thread size_t PAD1 CALIGN TLSMODEL __attribute__(( unused )); // protect false sharing 370 370 static __thread Heap * heapManager CALIGN TLSMODEL; 371 static __thread bool heapManagerBootFlag CALIGN TLSMODEL = false; 371 372 static __thread size_t PAD2 CALIGN TLSMODEL __attribute__(( unused )); // protect further false sharing 372 373 … … 488 489 allocUnfreed = 0; 489 490 #endif // __CFA_DEBUG__ 491 heapManagerBootFlag = true; 490 492 } // with 491 493 } // if … … 499 501 500 502 lock( heapMaster.mgrLock ); // protect heapMaster counters 503 504 assert( ! heapManagerBootFlag ); 501 505 502 506 // get storage for heap manager … … 514 518 515 519 void heapManagerDtor() libcfa_public { 520 if ( unlikely( ! heapManagerBootFlag ) ) return; // thread never used ? 521 516 522 lock( heapMaster.mgrLock ); 517 523 … … 521 527 522 528 #ifdef __STATISTICS__ 529 heapMaster.stats += heapManager->stats; // retain this heap's statistics 523 530 heapMaster.threads_exited += 1; 524 531 #endif // __STATISTICS__ … … 526 533 // Do not set heapManager to NULL because it is used after Cforall is shutdown but before the program shuts down. 527 534 535 heapManagerBootFlag = false; 528 536 unlock( heapMaster.mgrLock ); 529 537 } // heapManagerDtor … … 535 543 extern int cfa_main_returned; // from interpose.cfa 536 544 extern "C" { 537 void memory_startup( void ) { 545 void memory_startup( void ) { // singleton => called once at start of program 538 546 if ( ! heapMasterBootFlag ) heapManagerCtor(); // sanity check 539 547 } // memory_startup … … 557 565 fclose( stdin ); fclose( stdout ); // free buffer storage 558 566 if ( ! cfa_main_returned ) return; // do not check unfreed storage if exit called 567 568 #ifdef __STATISTICS__ 569 if ( getenv( "CFA_MALLOC_STATS" ) ) { // check for external printing 570 malloc_stats(); 571 } // if 572 #endif // __STATISTICS__ 559 573 560 574 #ifdef __CFA_DEBUG__ … … 895 909 #endif // __STATISTICS__ 896 910 911 // Uncomment to get allocation addresses for a 0-sized allocation rather than a null pointer. 912 //#define __NONNULL_0_ALLOC__ 913 #if ! defined( __NONNULL_0_ALLOC__ ) 914 #define __NULL_0_ALLOC__ unlikely( size == 0 ) || /* 0 BYTE ALLOCATION RETURNS NULL POINTER */ 915 #else 916 #define __NULL_0_ALLOC__ 917 #endif // __NONNULL_0_ALLOC__ 918 897 919 #define PROLOG( counter, ... ) \ 898 920 BOOT_HEAP_MANAGER; \ 899 if ( unlikely( size == 0 ) || /* 0 BYTE ALLOCATION RETURNS NULL POINTER */ \ 921 if ( \ 922 __NULL_0_ALLOC__ \ 900 923 unlikely( size > ULONG_MAX - sizeof(Heap.Storage) ) ) { /* error check */ \ 901 924 STAT_0_CNT( counter ); \ -
libcfa/src/iostream.cfa
r92355883 r2a301ff 10 10 // Created On : Wed May 27 17:56:53 2015 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Mon Jan 9 09:27:58202313 // Update Count : 1 36112 // Last Modified On : Thu Aug 31 11:27:56 2023 13 // Update Count : 1545 14 14 // 15 15 … … 21 21 #include <float.h> // DBL_DIG, LDBL_DIG 22 22 #include <complex.h> // creal, cimag 23 //#include <string.h> // strlen, strcmp, memcpy 23 //#include <stdio.h> 24 24 25 extern "C" { 25 26 extern size_t strlen (const char *__s) __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__pure__)) __attribute__ ((__nonnull__ (1))); … … 34 35 #pragma GCC visibility push(default) 35 36 37 36 38 // *********************************** ostream *********************************** 37 39 … … 43 45 return os; 44 46 } // ?|? 45 void ?|?( ostype & os, bool b ) { 46 (ostype &)(os | b); ends( os ); 47 } // ?|? 47 OSTYPE_VOID_IMPL( bool ) 48 48 49 49 ostype & ?|?( ostype & os, char c ) { 50 50 fmt( os, "%c", c ); 51 51 if ( c == '\n' ) setNL$( os, true ); 52 return sepOff( os ); 53 } // ?|? 54 void ?|?( ostype & os, char c ) { 55 (ostype &)(os | c); ends( os ); 56 } // ?|? 52 return nosep( os ); 53 } // ?|? 54 OSTYPE_VOID_IMPL( char ) 57 55 58 56 ostype & ?|?( ostype & os, signed char sc ) { … … 61 59 return os; 62 60 } // ?|? 63 void ?|?( ostype & os, signed char sc ) { 64 (ostype &)(os | sc); ends( os ); 65 } // ?|? 61 OSTYPE_VOID_IMPL( signed char ) 66 62 67 63 ostype & ?|?( ostype & os, unsigned char usc ) { … … 70 66 return os; 71 67 } // ?|? 72 void ?|?( ostype & os, unsigned char usc ) { 73 (ostype &)(os | usc); ends( os ); 74 } // ?|? 68 OSTYPE_VOID_IMPL( unsigned char ) 75 69 76 70 ostype & ?|?( ostype & os, short int si ) { … … 79 73 return os; 80 74 } // ?|? 81 void & ?|?( ostype & os, short int si ) { 82 (ostype &)(os | si); ends( os ); 83 } // ?|? 75 OSTYPE_VOID_IMPL( short int ) 84 76 85 77 ostype & ?|?( ostype & os, unsigned short int usi ) { … … 88 80 return os; 89 81 } // ?|? 90 void & ?|?( ostype & os, unsigned short int usi ) { 91 (ostype &)(os | usi); ends( os ); 92 } // ?|? 82 OSTYPE_VOID_IMPL( unsigned short int ) 93 83 94 84 ostype & ?|?( ostype & os, int i ) { … … 97 87 return os; 98 88 } // ?|? 99 void & ?|?( ostype & os, int i ) { 100 (ostype &)(os | i); ends( os ); 101 } // ?|? 89 OSTYPE_VOID_IMPL( int ) 102 90 103 91 ostype & ?|?( ostype & os, unsigned int ui ) { … … 106 94 return os; 107 95 } // ?|? 108 void & ?|?( ostype & os, unsigned int ui ) { 109 (ostype &)(os | ui); ends( os ); 110 } // ?|? 96 OSTYPE_VOID_IMPL( unsigned int ) 111 97 112 98 ostype & ?|?( ostype & os, long int li ) { … … 115 101 return os; 116 102 } // ?|? 117 void & ?|?( ostype & os, long int li ) { 118 (ostype &)(os | li); ends( os ); 119 } // ?|? 103 OSTYPE_VOID_IMPL( long int ) 120 104 121 105 ostype & ?|?( ostype & os, unsigned long int uli ) { … … 124 108 return os; 125 109 } // ?|? 126 void & ?|?( ostype & os, unsigned long int uli ) { 127 (ostype &)(os | uli); ends( os ); 128 } // ?|? 110 OSTYPE_VOID_IMPL( unsigned long int ) 129 111 130 112 ostype & ?|?( ostype & os, long long int lli ) { … … 133 115 return os; 134 116 } // ?|? 135 void & ?|?( ostype & os, long long int lli ) { 136 (ostype &)(os | lli); ends( os ); 137 } // ?|? 117 OSTYPE_VOID_IMPL( long long int ) 138 118 139 119 ostype & ?|?( ostype & os, unsigned long long int ulli ) { … … 142 122 return os; 143 123 } // ?|? 144 void & ?|?( ostype & os, unsigned long long int ulli ) { 145 (ostype &)(os | ulli); ends( os ); 146 } // ?|? 124 OSTYPE_VOID_IMPL( unsigned long long int ) 147 125 148 126 #if defined( __SIZEOF_INT128__ ) … … 176 154 return os; 177 155 } // ?|? 178 void & ?|?( ostype & os, int128 llli ) { 179 (ostype &)(os | llli); ends( os ); 180 } // ?|? 156 OSTYPE_VOID_IMPL( int128 ) 181 157 182 158 ostype & ?|?( ostype & os, unsigned int128 ullli ) { … … 185 161 return os; 186 162 } // ?|? 187 void & ?|?( ostype & os, unsigned int128 ullli ) { 188 (ostype &)(os | ullli); ends( os ); 189 } // ?|? 163 OSTYPE_VOID_IMPL( unsigned int128 ) 190 164 #endif // __SIZEOF_INT128__ 191 165 192 #define P rintWithDP( os, format, val, ... ) \166 #define PRINT_WITH_DP( os, format, val, ... ) \ 193 167 { \ 194 168 enum { size = 48 }; \ … … 199 173 for ( i; 0 ~ @ ) { \ 200 174 if ( i == len ) { fmt( os, "." ); break; } \ 201 if ( buf[i] == '.' || buf[i] == 'e' || buf[i] == 'E' ) break; /* decimal point or scientific ? */ \ 175 if ( buf[i] == '.' || buf[i] == 'e' || buf[i] == 'E' || \ 176 buf[i] == 'p' || buf[i] == 'P' ) break; /* decimal point or scientific ? */ \ 202 177 } /* for */ \ 203 178 } /* if */ \ … … 206 181 ostype & ?|?( ostype & os, float f ) { 207 182 if ( sepPrt$( os ) ) fmt( os, "%s", sepGetCur$( os ) ); 208 PrintWithDP( os, "%'g", f ); 209 return os; 210 } // ?|? 211 void & ?|?( ostype & os, float f ) { 212 (ostype &)(os | f); ends( os ); 213 } // ?|? 183 PRINT_WITH_DP( os, "%'g", f ); 184 return os; 185 } // ?|? 186 OSTYPE_VOID_IMPL( float ) 214 187 215 188 ostype & ?|?( ostype & os, double d ) { 216 189 if ( sepPrt$( os ) ) fmt( os, "%s", sepGetCur$( os ) ); 217 PrintWithDP( os, "%'.*lg", d, DBL_DIG ); 218 return os; 219 } // ?|? 220 void & ?|?( ostype & os, double d ) { 221 (ostype &)(os | d); ends( os ); 222 } // ?|? 190 PRINT_WITH_DP( os, "%'.*lg", d, DBL_DIG ); 191 return os; 192 } // ?|? 193 OSTYPE_VOID_IMPL( double ) 223 194 224 195 ostype & ?|?( ostype & os, long double ld ) { 225 196 if ( sepPrt$( os ) ) fmt( os, "%s", sepGetCur$( os ) ); 226 PrintWithDP( os, "%'.*Lg", ld, LDBL_DIG ); 227 return os; 228 } // ?|? 229 void & ?|?( ostype & os, long double ld ) { 230 (ostype &)(os | ld); ends( os ); 231 } // ?|? 197 PRINT_WITH_DP( os, "%'.*Lg", ld, LDBL_DIG ); 198 return os; 199 } // ?|? 200 OSTYPE_VOID_IMPL( long double ) 232 201 233 202 ostype & ?|?( ostype & os, float _Complex fc ) { 234 203 if ( sepPrt$( os ) ) fmt( os, "%s", sepGetCur$( os ) ); 235 204 // os | crealf( fc ) | nonl; 236 P rintWithDP( os, "%'g", crealf( fc ) );237 P rintWithDP( os, "%'+g", cimagf( fc ) );205 PRINT_WITH_DP( os, "%'g", crealf( fc ) ); 206 PRINT_WITH_DP( os, "%'+g", cimagf( fc ) ); 238 207 fmt( os, "i" ); 239 208 return os; 240 209 } // ?|? 241 void & ?|?( ostype & os, float _Complex fc ) { 242 (ostype &)(os | fc); ends( os ); 243 } // ?|? 210 OSTYPE_VOID_IMPL( float _Complex ) 244 211 245 212 ostype & ?|?( ostype & os, double _Complex dc ) { 246 213 if ( sepPrt$( os ) ) fmt( os, "%s", sepGetCur$( os ) ); 247 214 // os | creal( dc ) | nonl; 248 P rintWithDP( os, "%'.*lg", creal( dc ), DBL_DIG );249 P rintWithDP( os, "%'+.*lg", cimag( dc ), DBL_DIG );215 PRINT_WITH_DP( os, "%'.*lg", creal( dc ), DBL_DIG ); 216 PRINT_WITH_DP( os, "%'+.*lg", cimag( dc ), DBL_DIG ); 250 217 fmt( os, "i" ); 251 218 return os; 252 219 } // ?|? 253 void & ?|?( ostype & os, double _Complex dc ) { 254 (ostype &)(os | dc); ends( os ); 255 } // ?|? 220 OSTYPE_VOID_IMPL( double _Complex ) 256 221 257 222 ostype & ?|?( ostype & os, long double _Complex ldc ) { 258 223 if ( sepPrt$( os ) ) fmt( os, "%s", sepGetCur$( os ) ); 259 224 // os | creall( ldc ) || nonl; 260 P rintWithDP( os, "%'.*Lg", creall( ldc ), LDBL_DIG );261 P rintWithDP( os, "%'+.*Lg", cimagl( ldc ), LDBL_DIG );225 PRINT_WITH_DP( os, "%'.*Lg", creall( ldc ), LDBL_DIG ); 226 PRINT_WITH_DP( os, "%'+.*Lg", cimagl( ldc ), LDBL_DIG ); 262 227 fmt( os, "i" ); 263 228 return os; 264 229 } // ?|? 265 void & ?|?( ostype & os, long double _Complex ldc ) { 266 (ostype &)(os | ldc); ends( os ); 267 } // ?|? 230 OSTYPE_VOID_IMPL( long double _Complex ) 268 231 269 232 ostype & ?|?( ostype & os, const char s[] ) { 270 233 enum { Open = 1, Close, OpenClose }; 271 static const unsigned char mask[256] @= { 234 static const unsigned char mask[256] @= { // 256 covers all Latin-1 characters 272 235 // opening delimiters, no space after 273 236 ['('] : Open, ['['] : Open, ['{'] : Open, … … 284 247 285 248 if ( s == 0p ) { fmt( os, "%s", "0p" ); return os; } // null pointer 286 if ( s[0] == '\0' ) { sepOff( os ); return os; } // null string => noseparator249 if ( s[0] == '\0' ) { nosep( os ); return os; } // null string => no leading/trailing separator 287 250 288 251 // first character IS NOT spacing or closing punctuation => add left separator … … 300 263 fmt( os, "%s", s ); // fmt resets seperator, but reset it again 301 264 if ( sepPrt$( os ) && mask[ ch ] != Open && mask[ ch ] != OpenClose ) { 302 sep On( os );265 sep( os ); 303 266 } else { 304 sepOff( os );267 nosep( os ); 305 268 } // if 306 269 if ( ch == '\n' ) setNL$( os, true ); // check *AFTER* sepPrt$ call above as it resets NL flag … … 308 271 // return write( os, s, len ); 309 272 } // ?|? 310 void ?|?( ostype & os, const char s[] ) { 311 (ostype &)(os | s); ends( os ); 312 } // ?|? 313 314 // ostype & ?|?( ostype & os, const char16_t * s ) { 273 OSTYPE_VOID_IMPL( const char * ) 274 275 // ostype & ?|?( ostype & os, const char16_t s[] ) { 315 276 // if ( sepPrt$( os ) ) fmt( os, "%s", sepGetCur$( os ) ); 316 277 // fmt( os, "%ls", s ); … … 319 280 320 281 // #if ! ( __ARM_ARCH_ISA_ARM == 1 && __ARM_32BIT_STATE == 1 ) // char32_t == wchar_t => ambiguous 321 // ostype & ?|?( ostype & os, const char32_t * s) {282 // ostype & ?|?( ostype & os, const char32_t s[] ) { 322 283 // if ( sepPrt$( os ) ) fmt( os, "%s", sepGetCur$( os ) ); 323 284 // fmt( os, "%ls", s ); … … 326 287 // #endif // ! ( __ARM_ARCH_ISA_ARM == 1 && __ARM_32BIT_STATE == 1 ) 327 288 328 // ostype & ?|?( ostype & os, const wchar_t * s) {289 // ostype & ?|?( ostype & os, const wchar_t s[] ) { 329 290 // if ( sepPrt$( os ) ) fmt( os, "%s", sepGetCur$( os ) ); 330 291 // fmt( os, "%ls", s ); … … 337 298 return os; 338 299 } // ?|? 339 void ?|?( ostype & os, const void * p ) { 340 (ostype &)(os | p); ends( os ); 341 } // ?|? 300 OSTYPE_VOID_IMPL( const void * ) 342 301 343 302 // manipulators … … 351 310 } // ?|? 352 311 353 ostype & sep( ostype & os ) {354 return (ostype &)(os | sepGet( os ));355 } // sep356 357 ostype & sepTuple( ostype & os ) {358 return os | sepGetTuple( os );359 } // sepTuple360 361 312 ostype & nl( ostype & os ) { 362 313 (ostype &)(os | '\n'); 363 314 setPrt$( os, false ); // turn off 364 315 setNL$( os, true ); 365 return sepOff( os );// prepare for next line316 return nosep( os ); // prepare for next line 366 317 } // nl 367 318 … … 371 322 } // nonl 372 323 324 ostype & nlOn( ostype & os ) { 325 nlOn( os ); // call void returning 326 return os; 327 } // nlOn 328 329 ostype & nlOff( ostype & os ) { 330 nlOff( os ); // call void returning 331 return os; 332 } // nlOff 333 334 ostype & sepVal( ostype & os ) { 335 return (ostype &)(os | sepGet( os )); 336 } // sepVal 337 338 ostype & sepTupleVal( ostype & os ) { 339 return os | sepGetTuple( os ); 340 } // sepTupleVal 341 342 ostype & sep( ostype & os ) { 343 sep( os ); // call void returning 344 return os; 345 } // sep 346 347 ostype & nosep( ostype & os ) { 348 nosep( os ); // call void returning 349 return os; 350 } // nosep 351 373 352 ostype & sepOn( ostype & os ) { 374 353 sepOn( os ); // call void returning … … 380 359 return os; 381 360 } // sepOff 382 383 ostype & sepEnable( ostype & os ) {384 sepEnable( os ); // call void returning385 return os;386 } // sepEnable387 388 ostype & sepDisable( ostype & os ) {389 sepDisable( os ); // call void returning390 return os;391 } // sepDisable392 393 ostype & nlOn( ostype & os ) {394 nlOn( os ); // call void returning395 return os;396 } // nlOn397 398 ostype & nlOff( ostype & os ) {399 nlOff( os ); // call void returning400 return os;401 } // nlOff402 361 } // distribution 403 362 … … 442 401 443 402 // Default prefix for non-decimal prints is 0b, 0, 0x. 444 #define I ntegralFMTImpl( T, IFMTNP, IFMTP ) \403 #define INTEGRAL_FMT_IMPL( T, IFMTNP, IFMTP ) \ 445 404 forall( ostype & | basic_ostream( ostype ) ) { \ 446 405 ostype & ?|?( ostype & os, _Ostream_Manip(T) f ) { \ … … 508 467 fmtstr[star] = '%'; \ 509 468 \ 469 /* Special case printing 0 in hexadecimal as printf does not put the base. */ \ 470 if ( (f.base == 'x' | f.base == 'X') && ! f.flags.nobsdp && f.val == 0 ) { \ 471 fmt( os, f.base == 'x' ? "0x" : "0X" ); \ 472 f.wd -= 2; \ 473 if ( f.wd < 0 ) f.wd = 1; \ 474 } /* if */ \ 475 \ 510 476 if ( ! f.flags.pc ) { /* no precision */ \ 511 477 fmtstr[sizeof(IFMTNP)-2] = f.base; /* sizeof includes '\0' */ \ … … 519 485 return os; \ 520 486 } /* ?|? */ \ 521 void ?|?( ostype & os, _Ostream_Manip(T) f ) { \ 522 (ostype &)(os | f); ends( os ); \ 523 } /* ?|? */ \ 524 } // distribution 525 526 IntegralFMTImpl( signed char, " *hh ", " *.*hh " ) 527 IntegralFMTImpl( unsigned char, " *hh ", " *.*hh " ) 528 IntegralFMTImpl( signed short int, " *h ", " *.*h " ) 529 IntegralFMTImpl( unsigned short int, " *h ", " *.*h " ) 530 IntegralFMTImpl( signed int, " * ", " *.* " ) 531 IntegralFMTImpl( unsigned int, " * ", " *.* " ) 532 IntegralFMTImpl( signed long int, " *l ", " *.*l " ) 533 IntegralFMTImpl( unsigned long int, " *l ", " *.*l " ) 534 IntegralFMTImpl( signed long long int, " *ll ", " *.*ll " ) 535 IntegralFMTImpl( unsigned long long int, " *ll ", " *.*ll " ) 487 OSTYPE_VOID_IMPL( _Ostream_Manip(T) ) \ 488 } // distribution 489 490 INTEGRAL_FMT_IMPL( signed char, " *hh ", " *.*hh " ) 491 INTEGRAL_FMT_IMPL( unsigned char, " *hh ", " *.*hh " ) 492 INTEGRAL_FMT_IMPL( signed short int, " *h ", " *.*h " ) 493 INTEGRAL_FMT_IMPL( unsigned short int, " *h ", " *.*h " ) 494 INTEGRAL_FMT_IMPL( signed int, " * ", " *.* " ) 495 INTEGRAL_FMT_IMPL( unsigned int, " * ", " *.* " ) 496 INTEGRAL_FMT_IMPL( signed long int, " *l ", " *.*l " ) 497 INTEGRAL_FMT_IMPL( unsigned long int, " *l ", " *.*l " ) 498 INTEGRAL_FMT_IMPL( signed long long int, " *ll ", " *.*ll " ) 499 INTEGRAL_FMT_IMPL( unsigned long long int, " *ll ", " *.*ll " ) 536 500 537 501 … … 550 514 if ( cnt == 1 ) { 551 515 if ( f.flags.left ) { wd -= maxdig; f.wd = wd < 0 ? 1 : wd; } // update and restore f.wd for printing end chunk 552 sepOff( os ); // no seperator between chunks516 nosep( os ); // no seperator between chunks 553 517 } // if 554 518 } else { // print start chunk … … 595 559 else { f.pc = maxdig; f.flags.pc = true; } // left pad with precision 596 560 597 if ( cnt != 0 ) sepOff( os ); // no seperator between chunks561 if ( cnt != 0 ) nosep( os ); // no seperator between chunks 598 562 f.wd = wd; // reset f.wd for next chunk 599 563 f.flags.sign = false; // no leading +/- sign … … 602 566 } // base_128 603 567 604 #define I ntegralFMTImpl128( T ) \568 #define INTEGRAL_FMT_IMPL128( T ) \ 605 569 forall( ostype & | basic_ostream( ostype ) ) { \ 606 570 ostype & ?|?( ostype & os, _Ostream_Manip(T) f ) { \ … … 619 583 return os; \ 620 584 } /* ?|? */ \ 621 void ?|?( ostype & os, _Ostream_Manip(T) f ) { (ostype &)(os | f); ends( os ); }\622 } // distribution 623 624 I ntegralFMTImpl128( int128 )625 I ntegralFMTImpl128( unsigned int128 )585 OSTYPE_VOID_IMPL( _Ostream_Manip(T) ) \ 586 } // distribution 587 588 INTEGRAL_FMT_IMPL128( int128 ) 589 INTEGRAL_FMT_IMPL128( unsigned int128 ) 626 590 #endif // __SIZEOF_INT128__ 627 591 … … 635 599 #define SUFFIXES_END (SUFFIXES_START + (int)((sizeof(suffixes) / sizeof(char *) - 1) * 3)) 636 600 637 #define P rintWithDP2( os, format, ... ) \601 #define PRINT_WITH_DP2( os, format, ... ) \ 638 602 { \ 639 603 if ( ! f.flags.eng ) { \ 640 604 len = snprintf( buf, size, format, ##__VA_ARGS__ ); \ 641 if ( isfinite( f.val ) && ( f.pc != 0 || ! f.flags.nobsdp ) ) { /* if number, print decimal point when no fraction or exponent */ \ 642 for ( i = 0; i < len && buf[i] != '.' && buf[i] != 'e' && buf[i] != 'E'; i += 1 ); /* decimal point or scientific ? */ \ 605 if ( isfinite( f.val ) && ! f.flags.nobsdp ) { /* if number, print decimal point when no fraction or exponent */ \ 606 for ( i = 0; i < len && buf[i] != '.' && buf[i] != 'e' && buf[i] != 'E' && \ 607 buf[i] != 'p' && buf[i] != 'P'; i += 1 ); /* decimal point or scientific ? */ \ 643 608 if ( i == len ) { \ 644 609 if ( ! f.flags.left ) { \ … … 676 641 } 677 642 678 #define F loatingPointFMTImpl( T, DFMTNP, DFMTP ) \643 #define FLOATING_POINT_FMT_IMPL( T, DFMTNP, DFMTP ) \ 679 644 forall( ostype & | basic_ostream( ostype ) ) { \ 680 645 static void eng( T &value, int & pc, int & exp10 ) { \ … … 707 672 fmtstr[sizeof(DFMTNP)-2] = f.base; /* sizeof includes '\0' */ \ 708 673 /* printf( "%g %d %s\n", f.val, f.wd, &fmtstr[star] ); */ \ 709 P rintWithDP2( os, &fmtstr[star], f.wd, f.val ) \674 PRINT_WITH_DP2( os, &fmtstr[star], f.wd, f.val ) \ 710 675 } else { /* precision */ \ 711 676 fmtstr[sizeof(DFMTP)-2] = f.base; /* sizeof includes '\0' */ \ 712 677 /* printf( "%g %d %d %s\n", f.val, f.wd, f.pc, &fmtstr[star] ); */ \ 713 P rintWithDP2( os, &fmtstr[star], f.wd, f.pc, f.val ) \678 PRINT_WITH_DP2( os, &fmtstr[star], f.wd, f.pc, f.val ) \ 714 679 } /* if */ \ 715 680 return os; \ 716 681 } /* ?|? */ \ 717 682 \ 718 void ?|?( ostype & os, _Ostream_Manip(T) f ) { (ostype &)(os | f); ends( os ); }\719 } // distribution 720 721 F loatingPointFMTImpl( double, " * ", " *.* " )722 F loatingPointFMTImpl( long double, " *L ", " *.*L " )683 OSTYPE_VOID_IMPL( _Ostream_Manip(T) ) \ 684 } // distribution 685 686 FLOATING_POINT_FMT_IMPL( double, " * ", " *.* " ) 687 FLOATING_POINT_FMT_IMPL( long double, " *L ", " *.*L " ) 723 688 724 689 // *********************************** character *********************************** … … 751 716 return os; 752 717 } // ?|? 753 754 void ?|?( ostype & os, _Ostream_Manip(char) f ) { (ostype &)(os | f); ends( os ); } 718 OSTYPE_VOID_IMPL( _Ostream_Manip(char) ) 755 719 } // distribution 756 720 … … 773 737 } // if 774 738 775 if ( sepPrt$( os ) ) fmt( os, "%s", sepGetCur$( os ) ); 739 if ( f.val[0] != '\0' && // null string => no leading separator 740 sepPrt$( os ) ) fmt( os, "%s", sepGetCur$( os ) ); 776 741 777 742 #define SFMTNP "% * " … … 795 760 fmt( os, &fmtstr[star], f.wd, f.pc, f.val ); 796 761 } // if 797 return os;798 } // ?|?799 800 void ?|?( ostype & os, _Ostream_Manip(const char *) f ) { (ostype &)(os | f); ends( os ); }762 if ( f.val[0] == '\0' ) { nosep( os ); } // null string => no trailing separator 763 return os; 764 } // ?|? 765 OSTYPE_VOID_IMPL( _Ostream_Manip(const char *) ) 801 766 } // distribution 802 767 … … 817 782 return is; 818 783 } // ?|? 819 void ?|?( istype & is, bool & b ) { 820 (istype &)(is | b); ends( is ); 821 } // ?|? 784 ISTYPE_VOID_IMPL( bool & ) 822 785 823 786 istype & ?|?( istype & is, char & c ) { … … 831 794 return is; 832 795 } // ?|? 833 void ?|?( istype & is, char & c ) { 834 (istype &)(is | c); ends( is ); 835 } // ?|? 796 ISTYPE_VOID_IMPL( char & ) 836 797 837 798 istype & ?|?( istype & is, signed char & sc ) { … … 839 800 return is; 840 801 } // ?|? 841 void ?|?( istype & is, signed char & sc ) { 842 (istype &)(is | sc); ends( is ); 843 } // ?|? 802 ISTYPE_VOID_IMPL( signed char & ) 844 803 845 804 istype & ?|?( istype & is, unsigned char & usc ) { … … 847 806 return is; 848 807 } // ?|? 849 void ?|?( istype & is, unsigned char & usc ) { 850 (istype &)(is | usc); ends( is ); 851 } // ?|? 808 ISTYPE_VOID_IMPL( unsigned char & ) 852 809 853 810 istype & ?|?( istype & is, short int & si ) { … … 855 812 return is; 856 813 } // ?|? 857 void ?|?( istype & is, short int & si ) { 858 (istype &)(is | si); ends( is ); 859 } // ?|? 814 ISTYPE_VOID_IMPL( short int & ) 860 815 861 816 istype & ?|?( istype & is, unsigned short int & usi ) { … … 863 818 return is; 864 819 } // ?|? 865 void ?|?( istype & is, unsigned short int & usi ) { 866 (istype &)(is | usi); ends( is ); 867 } // ?|? 820 ISTYPE_VOID_IMPL( unsigned short int & ) 868 821 869 822 istype & ?|?( istype & is, int & i ) { … … 871 824 return is; 872 825 } // ?|? 873 void ?|?( istype & is, int & i ) { 874 (istype &)(is | i); ends( is ); 875 } // ?|? 826 ISTYPE_VOID_IMPL( int & ) 876 827 877 828 istype & ?|?( istype & is, unsigned int & ui ) { … … 879 830 return is; 880 831 } // ?|? 881 void ?|?( istype & is, unsigned int & ui ) { 882 (istype &)(is | ui); ends( is ); 883 } // ?|? 832 ISTYPE_VOID_IMPL( unsigned int & ) 884 833 885 834 istype & ?|?( istype & is, long int & li ) { … … 887 836 return is; 888 837 } // ?|? 889 void ?|?( istype & is, long int & li ) { 890 (istype &)(is | li); ends( is ); 891 } // ?|? 838 ISTYPE_VOID_IMPL( long int & ) 892 839 893 840 istype & ?|?( istype & is, unsigned long int & ulli ) { … … 895 842 return is; 896 843 } // ?|? 897 void ?|?( istype & is, unsigned long int & ulli ) { 898 (istype &)(is | ulli); ends( is ); 899 } // ?|? 844 ISTYPE_VOID_IMPL( unsigned long int & ) 900 845 901 846 istype & ?|?( istype & is, long long int & lli ) { … … 903 848 return is; 904 849 } // ?|? 905 void ?|?( istype & is, long long int & lli ) { 906 (istype &)(is | lli); ends( is ); 907 } // ?|? 850 ISTYPE_VOID_IMPL( long long int & ) 908 851 909 852 istype & ?|?( istype & is, unsigned long long int & ulli ) { … … 911 854 return is; 912 855 } // ?|? 913 void & ?|?( istype & is, unsigned long long int & ulli ) { 914 (istype &)(is | ulli); ends( is ); 915 } // ?|? 856 ISTYPE_VOID_IMPL( unsigned long long int & ) 916 857 917 858 #if defined( __SIZEOF_INT128__ ) … … 919 860 return (istype &)(is | (unsigned int128 &)llli); 920 861 } // ?|? 921 void ?|?( istype & is, int128 & llli ) { 922 (istype &)(is | llli); ends( is ); 923 } // ?|? 862 ISTYPE_VOID_IMPL( int128 & ) 924 863 925 864 istype & ?|?( istype & is, unsigned int128 & ullli ) { … … 938 877 return is; 939 878 } // ?|? 940 void ?|?( istype & is, unsigned int128 & ullli ) { 941 (istype &)(is | ullli); ends( is ); 942 } // ?|? 879 ISTYPE_VOID_IMPL( unsigned int128 & ) 943 880 #endif // __SIZEOF_INT128__ 944 881 … … 947 884 return is; 948 885 } // ?|? 949 void ?|?( istype & is, float & f ) { 950 (istype &)(is | f); ends( is ); 951 } // ?|? 886 ISTYPE_VOID_IMPL( float & ) 952 887 953 888 istype & ?|?( istype & is, double & d ) { … … 955 890 return is; 956 891 } // ?|? 957 void ?|?( istype & is, double & d ) { 958 (istype &)(is | d); ends( is ); 959 } // ?|? 892 ISTYPE_VOID_IMPL( double & ) 960 893 961 894 istype & ?|?( istype & is, long double & ld ) { … … 963 896 return is; 964 897 } // ?|? 965 void ?|?( istype & is, long double & ld ) { 966 (istype &)(is | ld); ends( is ); 967 } // ?|? 898 ISTYPE_VOID_IMPL( long double & ) 968 899 969 900 istype & ?|?( istype & is, float _Complex & fc ) { … … 973 904 return is; 974 905 } // ?|? 975 void ?|?( istype & is, float _Complex & fc ) { 976 (istype &)(is | fc); ends( is ); 977 } // ?|? 906 ISTYPE_VOID_IMPL( float _Complex & ) 978 907 979 908 istype & ?|?( istype & is, double _Complex & dc ) { … … 983 912 return is; 984 913 } // ?|? 985 void ?|?( istype & is, double _Complex & dc ) { 986 (istype &)(is | dc); ends( is ); 987 } // ?|? 914 ISTYPE_VOID_IMPL( double _Complex & ) 988 915 989 916 istype & ?|?( istype & is, long double _Complex & ldc ) { … … 993 920 return is; 994 921 } // ?|? 995 void ?|?( istype & is, long double _Complex & ldc ) { 996 (istype &)(is | ldc); ends( is ); 997 } // ?|? 922 ISTYPE_VOID_IMPL( long double _Complex & ) 998 923 999 924 // istype & ?|?( istype & is, const char fmt[] ) { … … 1002 927 // } // ?|? 1003 928 1004 istype & ?|?( istype & is, char s[] ) { 1005 fmt( is, "%s", s ); 1006 return is; 1007 } // ?|? 1008 void ?|?( istype & is, char s[] ) { 1009 (istype &)(is | s); ends( is ); 1010 } // ?|? 929 // istype & ?|?( istype & is, char s[] ) { 930 // fmt( is, "%s", s ); 931 // return is; 932 // } // ?|? 933 // ISTYPE_VOID_IMPL( char * ) 1011 934 1012 935 // manipulators … … 1014 937 return manip( is ); 1015 938 } // ?|? 939 1016 940 void ?|?( istype & is, istype & (* manip)( istype & ) ) { 1017 941 manip( is ); ends( is ); … … 1020 944 istype & nl( istype & is ) { 1021 945 fmt( is, "%*[^\n]" ); // ignore characters to newline 946 if ( ! eof( is ) && getANL$( is ) ) fmt( is, "%*c" ); // read newline 1022 947 return is; 1023 948 } // nl … … 1038 963 forall( istype & | basic_istream( istype ) ) { 1039 964 istype & ?|?( istype & is, _Istream_Cstr f ) { 1040 // skip xxx965 // skip 1041 966 if ( ! f.s ) { 1042 967 // printf( "skip %s %d\n", f.scanset, f.wd ); 1043 if ( f.wd == -1 ) fmt( is, f.scanset, "" ); // no input arguments968 if ( f.wd == -1 ) fmt( is, f.scanset, "" ); // no input arguments 1044 969 else for ( f.wd ) fmt( is, "%*c" ); 1045 970 return is; 1046 971 } // if 972 973 const char * scanset = f.scanset; 974 if ( f.flags.delimit ) scanset = f.delimit; // getline ? 975 1047 976 size_t len = 0; 1048 if ( f.scanset ) len = strlen( f.scanset );977 if ( scanset ) len = strlen( scanset ); 1049 978 char fmtstr[len + 16]; 1050 979 int start = 1; … … 1052 981 if ( f.flags.ignore ) { fmtstr[1] = '*'; start += 1; } 1053 982 if ( f.wd != -1 ) { start += sprintf( &fmtstr[start], "%d", f.wd ); } 1054 // cstr %s, %*s, %ws, %*ws 1055 if ( ! f.scanset ) { 983 984 if ( ! scanset ) { 985 // %s, %*s, %ws, %*ws 1056 986 fmtstr[start] = 's'; fmtstr[start + 1] = '\0'; 1057 987 // printf( "cstr %s\n", fmtstr ); 1058 fmt( is, fmtstr, f.s ); 1059 return is; 1060 } // if 1061 // incl %[xxx], %*[xxx], %w[xxx], %*w[xxx] 1062 // excl %[^xxx], %*[^xxx], %w[^xxx], %*w[^xxx] 1063 fmtstr[start] = '['; start += 1; 1064 if ( f.flags.inex ) { fmtstr[start] = '^'; start += 1; } 1065 strcpy( &fmtstr[start], f.scanset ); // copy includes '\0' 1066 len += start; 1067 fmtstr[len] = ']'; fmtstr[len + 1] = '\0'; 1068 // printf( "incl/excl %s\n", fmtstr ); 1069 fmt( is, fmtstr, f.s ); 1070 return is; 1071 } // ?|? 1072 void ?|?( istype & is, _Istream_Cstr f ) { 1073 (istype &)(is | f); ends( is ); 1074 } // ?|? 988 } else { 989 // incl %[xxx], %*[xxx], %w[xxx], %*w[xxx] 990 // excl %[^xxx], %*[^xxx], %w[^xxx], %*w[^xxx] 991 fmtstr[start] = '['; start += 1; 992 if ( f.flags.inex ) { fmtstr[start] = '^'; start += 1; } 993 strcpy( &fmtstr[start], scanset ); // copy includes '\0' 994 len += start; 995 fmtstr[len] = ']'; fmtstr[len + 1] = '\0'; 996 // printf( "incl/excl %s\n", fmtstr ); 997 } // if 998 999 int check = f.wd - 1; 1000 if ( ! f.flags.rwd ) f.s[check] = '\0'; // insert sentinel 1001 len = fmt( is, fmtstr, f.s ); 1002 //fprintf( stderr, "KK %s %zd %d %c %s\n", fmtstr, len, check, f.s[check], f.s ); 1003 1004 if ( ! f.flags.rwd && f.s[check] != '\0' ) // sentinel overwritten ? 1005 throw (cstring_length){ &cstring_length_vt }; 1006 1007 if ( f.flags.delimit ) { // getline ? 1008 if ( len == 0 ) f.s[0] = '\0'; // empty read => argument unchanged => set empty 1009 if ( ! eof( is ) ) fmt( is, "%*c" ); // ignore delimiter 1010 } //if 1011 return is; 1012 } // ?|? 1013 ISTYPE_VOID_IMPL( _Istream_Cstr ) 1075 1014 1076 1015 istype & ?|?( istype & is, _Istream_Char f ) { 1077 fmt( is, "%*c" ); // argument variable unused 1078 return is; 1079 } // ?|? 1080 void ?|?( istype & is, _Istream_Char f ) { 1081 (istype &)(is | f); ends( is ); 1082 } // ?|? 1083 } // distribution 1084 1085 #define InputFMTImpl( T, CODE ) \ 1016 fmt( is, "%*c" ); // argument variable unused 1017 return is; 1018 } // ?|? 1019 ISTYPE_VOID_IMPL( _Istream_Char ) 1020 } // distribution 1021 1022 #define INPUT_FMT_IMPL( T, CODE ) \ 1086 1023 forall( istype & | basic_istream( istype ) ) { \ 1087 1024 istype & ?|?( istype & is, _Istream_Manip(T) f ) { \ … … 1097 1034 return is; \ 1098 1035 } /* ?|? */ \ 1099 void ?|?( istype & is, _Istream_Manip(T) f ) { \ 1100 (istype &)(is | f); ends( is ); \ 1101 } /* ?|? */ \ 1102 } // distribution 1103 1104 InputFMTImpl( signed char, "hhi" ) 1105 InputFMTImpl( unsigned char, "hhi" ) 1106 InputFMTImpl( signed short int, "hi" ) 1107 InputFMTImpl( unsigned short int, "hi" ) 1108 InputFMTImpl( signed int, "i" ) 1109 InputFMTImpl( unsigned int, "i" ) 1110 InputFMTImpl( signed long int, "li" ) 1111 InputFMTImpl( unsigned long int, "li" ) 1112 InputFMTImpl( signed long long int, "lli" ) 1113 InputFMTImpl( unsigned long long int, "lli" ) 1114 1115 InputFMTImpl( float, "f" ) 1116 InputFMTImpl( double, "lf" ) 1117 InputFMTImpl( long double, "Lf" ) 1036 ISTYPE_VOID_IMPL( _Istream_Manip(T) ) \ 1037 } // distribution 1038 1039 INPUT_FMT_IMPL( signed char, "hhi" ) 1040 INPUT_FMT_IMPL( unsigned char, "hhi" ) 1041 INPUT_FMT_IMPL( signed short int, "hi" ) 1042 INPUT_FMT_IMPL( unsigned short int, "hi" ) 1043 INPUT_FMT_IMPL( signed int, "i" ) 1044 INPUT_FMT_IMPL( unsigned int, "i" ) 1045 INPUT_FMT_IMPL( signed long int, "li" ) 1046 INPUT_FMT_IMPL( unsigned long int, "li" ) 1047 INPUT_FMT_IMPL( signed long long int, "lli" ) 1048 INPUT_FMT_IMPL( unsigned long long int, "lli" ) 1049 1050 INPUT_FMT_IMPL( float, "f" ) 1051 INPUT_FMT_IMPL( double, "lf" ) 1052 INPUT_FMT_IMPL( long double, "Lf" ) 1118 1053 1119 1054 forall( istype & | basic_istream( istype ) ) { … … 1127 1062 return is; 1128 1063 } // ?|? 1129 void ?|?( istype & is, _Istream_Manip(float _Complex) fc ) { 1130 (istype &)(is | fc); ends( is ); 1131 } // ?|? 1064 ISTYPE_VOID_IMPL( _Istream_Manip(float _Complex) ) 1132 1065 1133 1066 istype & ?|?( istype & is, _Istream_Manip(double _Complex) dc ) { … … 1140 1073 return is; 1141 1074 } // ?|? 1142 void ?|?( istype & is, _Istream_Manip(double _Complex) dc ) { 1143 (istype &)(is | dc); ends( is ); 1144 } // ?|? 1075 ISTYPE_VOID_IMPL( _Istream_Manip(double _Complex) ) 1145 1076 1146 1077 istype & ?|?( istype & is, _Istream_Manip(long double _Complex) ldc ) { … … 1153 1084 return is; 1154 1085 } // ?|? 1155 void ?|?( istype & is, _Istream_Manip(long double _Complex) ldc ) { 1156 (istype &)(is | ldc); ends( is ); 1157 } // ?|? 1158 } // distribution 1086 ISTYPE_VOID_IMPL( _Istream_Manip(long double _Complex) ) 1087 } // distribution 1088 1159 1089 1160 1090 // Local Variables: // -
libcfa/src/iostream.hfa
r92355883 r2a301ff 10 10 // Created On : Wed May 27 17:56:53 2015 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Thu Jun 15 22:34:31202313 // Update Count : 41112 // Last Modified On : Thu Aug 31 10:55:35 2023 13 // Update Count : 544 14 14 // 15 15 … … 17 17 18 18 #include "iterator.hfa" 19 19 #include "Exception.hfa" 20 20 21 21 // *********************************** ostream *********************************** 22 23 22 24 23 forall( ostype & ) … … 30 29 const char * sepGetCur$( ostype & ); // get current separator string 31 30 void sepSetCur$( ostype &, const char [] ); // set current separator string 32 bool getNL$( ostype & ); // checknewline33 void setNL$( ostype &, bool ); // sawnewline31 bool getNL$( ostype & ); // get newline 32 bool setNL$( ostype &, bool ); // set newline 34 33 bool getANL$( ostype & ); // get auto newline (on/off) 34 bool setANL$( ostype &, bool ); // set auto newline (on/off), and return previous state 35 35 bool getPrt$( ostype & ); // get fmt called in output cascade 36 voidsetPrt$( ostype &, bool ); // set fmt called in output cascade36 bool setPrt$( ostype &, bool ); // set fmt called in output cascade 37 37 // public 38 void sepOn( ostype & ); // turn separator state on39 void sepOff( ostype & ); // turn separator state off40 bool sepDisable( ostype & ); // set default state to off, and return previous state41 bool sepEnable( ostype & ); // set default state to on, and return previous state42 38 void nlOn( ostype & ); // turn auto-newline state on 43 39 void nlOff( ostype & ); // turn auto-newline state off 44 40 41 void sep( ostype & ); // turn separator state on 42 void nosep( ostype & ); // turn separator state off 43 bool sepOn( ostype & ); // set default state to on, and return previous state 44 bool sepOff( ostype & ); // set default state to off, and return previous state 45 45 const char * sepGet( ostype & ); // get separator string 46 46 void sepSet( ostype &, const char [] ); // set separator to string (15 character maximum) … … 74 74 // implement writable for intrinsic types 75 75 76 #define OSTYPE_VOID( T ) void ?|?( ostype &, T ) 77 #define OSTYPE_VOID_IMPL( T ) \ 78 void ?|?( ostype & os, T t ) { \ 79 (ostype &)(os | t); ends( os ); \ 80 } // ?|? 81 76 82 forall( ostype & | basic_ostream( ostype ) ) { 77 83 ostype & ?|?( ostype &, bool ); 78 void ?|?( ostype &,bool );84 OSTYPE_VOID( bool ); 79 85 80 86 ostype & ?|?( ostype &, char ); 81 void ?|?( ostype &,char );87 OSTYPE_VOID( char ); 82 88 ostype & ?|?( ostype &, signed char ); 83 void ?|?( ostype &,signed char );89 OSTYPE_VOID( signed char ); 84 90 ostype & ?|?( ostype &, unsigned char ); 85 void ?|?( ostype &,unsigned char );91 OSTYPE_VOID( unsigned char ); 86 92 87 93 ostype & ?|?( ostype &, short int ); 88 void ?|?( ostype &,short int );94 OSTYPE_VOID( short int ); 89 95 ostype & ?|?( ostype &, unsigned short int ); 90 void ?|?( ostype &,unsigned short int );96 OSTYPE_VOID( unsigned short int ); 91 97 ostype & ?|?( ostype &, int ); 92 void ?|?( ostype &,int );98 OSTYPE_VOID( int ); 93 99 ostype & ?|?( ostype &, unsigned int ); 94 void ?|?( ostype &,unsigned int );100 OSTYPE_VOID( unsigned int ); 95 101 ostype & ?|?( ostype &, long int ); 96 void ?|?( ostype &,long int );102 OSTYPE_VOID( long int ); 97 103 ostype & ?|?( ostype &, long long int ); 98 void ?|?( ostype &,long long int );104 OSTYPE_VOID( long long int ); 99 105 ostype & ?|?( ostype &, unsigned long int ); 100 void ?|?( ostype &,unsigned long int );106 OSTYPE_VOID( unsigned long int ); 101 107 ostype & ?|?( ostype &, unsigned long long int ); 102 void ?|?( ostype &,unsigned long long int );108 OSTYPE_VOID( unsigned long long int ); 103 109 #if defined( __SIZEOF_INT128__ ) 104 110 ostype & ?|?( ostype &, int128 ); 105 void ?|?( ostype &,int128 );111 OSTYPE_VOID( int128 ); 106 112 ostype & ?|?( ostype &, unsigned int128 ); 107 void ?|?( ostype &,unsigned int128 );113 OSTYPE_VOID( unsigned int128 ); 108 114 #endif // __SIZEOF_INT128__ 109 115 110 116 ostype & ?|?( ostype &, float ); 111 void ?|?( ostype &,float );117 OSTYPE_VOID( float ); 112 118 ostype & ?|?( ostype &, double ); 113 void ?|?( ostype &,double );119 OSTYPE_VOID( double ); 114 120 ostype & ?|?( ostype &, long double ); 115 void ?|?( ostype &,long double );121 OSTYPE_VOID( long double ); 116 122 117 123 ostype & ?|?( ostype &, float _Complex ); 118 void ?|?( ostype &,float _Complex );124 OSTYPE_VOID( float _Complex ); 119 125 ostype & ?|?( ostype &, double _Complex ); 120 void ?|?( ostype &,double _Complex );126 OSTYPE_VOID( double _Complex ); 121 127 ostype & ?|?( ostype &, long double _Complex ); 122 void ?|?( ostype &,long double _Complex );128 OSTYPE_VOID( long double _Complex ); 123 129 124 130 ostype & ?|?( ostype &, const char [] ); 125 void ?|?( ostype &,const char [] );126 // ostype & ?|?( ostype &, const char16_t *);131 OSTYPE_VOID( const char [] ); 132 // ostype & ?|?( ostype &, const char16_t [] ); 127 133 #if ! ( __ARM_ARCH_ISA_ARM == 1 && __ARM_32BIT_STATE == 1 ) // char32_t == wchar_t => ambiguous 128 // ostype & ?|?( ostype &, const char32_t *);134 // ostype & ?|?( ostype &, const char32_t [] ); 129 135 #endif // ! ( __ARM_ARCH_ISA_ARM == 1 && __ARM_32BIT_STATE == 1 ) 130 // ostype & ?|?( ostype &, const wchar_t *);136 // ostype & ?|?( ostype &, const wchar_t [] ); 131 137 ostype & ?|?( ostype &, const void * ); 132 void ?|?( ostype &, const void * ); 138 OSTYPE_VOID( const void * ); 139 140 // FIX-ME: does not work so using macros 141 // forall( T | { ostype & ?|?( ostype &, T ); } ) 142 // void ?|?( ostype & os, T ); 133 143 134 144 // manipulators 135 145 ostype & ?|?( ostype &, ostype & (*)( ostype & ) ); 136 void ?|?( ostype &, ostype & (*)( ostype & ) ); 146 OSTYPE_VOID( ostype & (*)( ostype & ) ); 147 137 148 ostype & nl( ostype & ); 138 149 ostype & nonl( ostype & ); 150 ostype & nlOn( ostype & ); 151 ostype & nlOff( ostype & ); 152 153 ostype & sepVal( ostype & ); 154 ostype & sepTupleVal( ostype & ); 139 155 ostype & sep( ostype & ); 140 ostype & sepTuple( ostype & );156 ostype & nosep( ostype & ); 141 157 ostype & sepOn( ostype & ); 142 158 ostype & sepOff( ostype & ); 143 ostype & sepDisable( ostype & );144 ostype & sepEnable( ostype & );145 ostype & nlOn( ostype & );146 ostype & nlOff( ostype & );147 159 } // distribution 148 160 … … 188 200 // initialized explicitly shall be initialized implicitly the same as objects that have static storage duration.*** 189 201 190 #define I ntegralFMTDecl( T, CODE ) \202 #define INTEGRAL_FMT_DECL( T, CODE ) \ 191 203 static inline { \ 192 204 _Ostream_Manip(T) bin( T val ) { return (_Ostream_Manip(T))@{ val, 1, 0, 'b', { .all : 0 } }; } \ … … 206 218 forall( ostype & | basic_ostream( ostype ) ) { \ 207 219 ostype & ?|?( ostype & os, _Ostream_Manip(T) f ); \ 208 void ?|?( ostype & os, _Ostream_Manip(T) f); \220 OSTYPE_VOID( _Ostream_Manip(T) ); \ 209 221 } // ?|? 210 222 211 I ntegralFMTDecl( signed char, 'd' )212 I ntegralFMTDecl( unsigned char, 'u' )213 I ntegralFMTDecl( signed short int, 'd' )214 I ntegralFMTDecl( unsigned short int, 'u' )215 I ntegralFMTDecl( signed int, 'd' )216 I ntegralFMTDecl( unsigned int, 'u' )217 I ntegralFMTDecl( signed long int, 'd' )218 I ntegralFMTDecl( unsigned long int, 'u' )219 I ntegralFMTDecl( signed long long int, 'd' )220 I ntegralFMTDecl( unsigned long long int, 'u' )223 INTEGRAL_FMT_DECL( signed char, 'd' ) 224 INTEGRAL_FMT_DECL( unsigned char, 'u' ) 225 INTEGRAL_FMT_DECL( signed short int, 'd' ) 226 INTEGRAL_FMT_DECL( unsigned short int, 'u' ) 227 INTEGRAL_FMT_DECL( signed int, 'd' ) 228 INTEGRAL_FMT_DECL( unsigned int, 'u' ) 229 INTEGRAL_FMT_DECL( signed long int, 'd' ) 230 INTEGRAL_FMT_DECL( unsigned long int, 'u' ) 231 INTEGRAL_FMT_DECL( signed long long int, 'd' ) 232 INTEGRAL_FMT_DECL( unsigned long long int, 'u' ) 221 233 #if defined( __SIZEOF_INT128__ ) 222 I ntegralFMTDecl( int128, 'd' )223 I ntegralFMTDecl( unsigned int128, 'u' )234 INTEGRAL_FMT_DECL( int128, 'd' ) 235 INTEGRAL_FMT_DECL( unsigned int128, 'u' ) 224 236 #endif // __SIZEOF_INT128__ 225 237 … … 227 239 228 240 // Default suffix for values with no fraction is "." 229 #define F loatingPointFMTDecl( T ) \241 #define FLOATING_POINT_FMT_DECL( T ) \ 230 242 static inline { \ 231 243 _Ostream_Manip(T) hex( T val ) { return (_Ostream_Manip(T))@{ val, 1, 0, 'a', { .all : 0 } }; } \ … … 251 263 forall( ostype & | basic_ostream( ostype ) ) { \ 252 264 ostype & ?|?( ostype & os, _Ostream_Manip(T) f ); \ 253 void ?|?( ostype & os, _Ostream_Manip(T) f); \265 OSTYPE_VOID( _Ostream_Manip(T) ); \ 254 266 } // ?|? 255 267 256 F loatingPointFMTDecl( double )257 F loatingPointFMTDecl( long double )268 FLOATING_POINT_FMT_DECL( double ) 269 FLOATING_POINT_FMT_DECL( long double ) 258 270 259 271 // *********************************** character *********************************** … … 271 283 forall( ostype & | basic_ostream( ostype ) ) { 272 284 ostype & ?|?( ostype & os, _Ostream_Manip(char) f ); 273 void ?|?( ostype & os, _Ostream_Manip(char) f );285 OSTYPE_VOID( _Ostream_Manip(char) ); \ 274 286 } // ?|? 275 287 … … 289 301 forall( ostype & | basic_ostream( ostype ) ) { 290 302 ostype & ?|?( ostype & os, _Ostream_Manip(const char *) f ); 291 void ?|?( ostype & os, _Ostream_Manip(const char *) f );303 OSTYPE_VOID( _Ostream_Manip(const char *) ); \ 292 304 } // ?|? 293 305 294 295 306 // *********************************** istream *********************************** 296 307 308 #define ISTYPE_VOID( T ) void ?|?( istype &, T ) 309 #define ISTYPE_VOID_IMPL( T ) \ 310 void ?|?( istype & is, T t ) { \ 311 (istype &)(is | t); ends( is ); \ 312 } // ?|? 297 313 298 314 forall( istype & ) … … 300 316 // private 301 317 bool getANL$( istype & ); // get scan newline (on/off) 318 bool setANL$( istype &, bool ); // set scan newline (on/off) 302 319 // public 303 320 void nlOn( istype & ); // read newline … … 325 342 forall( istype & | basic_istream( istype ) ) { 326 343 istype & ?|?( istype &, bool & ); 327 void ?|?( istype &,bool & );344 ISTYPE_VOID( bool & ); 328 345 329 346 istype & ?|?( istype &, char & ); 330 void ?|?( istype &,char & );347 ISTYPE_VOID( char & ); 331 348 istype & ?|?( istype &, signed char & ); 332 void ?|?( istype &,signed char & );349 ISTYPE_VOID( signed char & ); 333 350 istype & ?|?( istype &, unsigned char & ); 334 void ?|?( istype &,unsigned char & );351 ISTYPE_VOID( unsigned char & ); 335 352 336 353 istype & ?|?( istype &, short int & ); 337 void ?|?( istype &,short int & );354 ISTYPE_VOID( short int & ); 338 355 istype & ?|?( istype &, unsigned short int & ); 339 void ?|?( istype &,unsigned short int & );356 ISTYPE_VOID( unsigned short int & ); 340 357 istype & ?|?( istype &, int & ); 341 void ?|?( istype &,int & );358 ISTYPE_VOID( int & ); 342 359 istype & ?|?( istype &, unsigned int & ); 343 void ?|?( istype &,unsigned int & );360 ISTYPE_VOID( unsigned int & ); 344 361 istype & ?|?( istype &, long int & ); 345 void ?|?( istype &,long int & );362 ISTYPE_VOID( long int & ); 346 363 istype & ?|?( istype &, unsigned long int & ); 347 void ?|?( istype &,unsigned long int & );364 ISTYPE_VOID( unsigned long int & ); 348 365 istype & ?|?( istype &, long long int & ); 349 void ?|?( istype &,long long int & );366 ISTYPE_VOID( long long int & ); 350 367 istype & ?|?( istype &, unsigned long long int & ); 351 void ?|?( istype &,unsigned long long int & );368 ISTYPE_VOID( unsigned long long int & ); 352 369 #if defined( __SIZEOF_INT128__ ) 353 370 istype & ?|?( istype &, int128 & ); 354 void ?|?( istype &,int128 & );371 ISTYPE_VOID( int128 & ); 355 372 istype & ?|?( istype &, unsigned int128 & ); 356 void ?|?( istype &,unsigned int128 & );373 ISTYPE_VOID( unsigned int128 & ); 357 374 #endif // __SIZEOF_INT128__ 358 375 359 376 istype & ?|?( istype &, float & ); 360 void ?|?( istype &,float & );377 ISTYPE_VOID( float & ); 361 378 istype & ?|?( istype &, double & ); 362 void ?|?( istype &,double & );379 ISTYPE_VOID( double & ); 363 380 istype & ?|?( istype &, long double & ); 364 void ?|?( istype &,long double & );381 ISTYPE_VOID( long double & ); 365 382 366 383 istype & ?|?( istype &, float _Complex & ); 367 void ?|?( istype &,float _Complex & );384 ISTYPE_VOID( float _Complex & ); 368 385 istype & ?|?( istype &, double _Complex & ); 369 void ?|?( istype &,double _Complex & );386 ISTYPE_VOID( double _Complex & ); 370 387 istype & ?|?( istype &, long double _Complex & ); 371 void ?|?( istype &,long double _Complex & );388 ISTYPE_VOID( long double _Complex & ); 372 389 373 390 // istype & ?|?( istype &, const char [] ); 374 istype & ?|?( istype &, char [] );375 void ?|?( istype &,char [] );391 // istype & ?|?( istype &, char [] ); 392 // ISTYPE_VOID( char [] ); 376 393 377 394 // manipulators 378 395 istype & ?|?( istype &, istype & (*)( istype & ) ); 379 void ?|?( istype &,istype & (*)( istype & ) );396 ISTYPE_VOID( istype & (*)( istype & ) ); 380 397 istype & nl( istype & is ); 381 398 istype & nlOn( istype & ); … … 383 400 } // distribution 384 401 402 // *********************************** exceptions *********************************** 403 404 ExceptionDecl( cstring_length ); 405 385 406 // *********************************** manipulators *********************************** 386 407 387 struct _Istream_Cstr { 388 char * s; 389 const char * scanset; 408 struct _Istream_str_base { 409 union { 410 const char * scanset; 411 char delimit[2]; 412 }; 390 413 int wd; // width 391 414 union { … … 394 417 unsigned char ignore:1; // do not change input argument 395 418 unsigned char inex:1; // include/exclude characters in scanset 419 unsigned char delimit:1; // delimit character 420 unsigned char rwd:1; // read width 396 421 } flags; 397 422 }; 423 }; // _Istream_str_base 424 425 struct _Istream_Cstr { 426 char * s; 427 inline _Istream_str_base; 398 428 }; // _Istream_Cstr 399 429 400 430 static inline { 401 _Istream_Cstr skip( const char scanset[] ) { return (_Istream_Cstr){ 0p, scanset, -1, { .all : 0 } }; } 402 _Istream_Cstr skip( unsigned int n ) { return (_Istream_Cstr){ 0p, 0p, n, { .all : 0 } }; } 403 _Istream_Cstr incl( const char scanset[], char * s ) { return (_Istream_Cstr){ s, scanset, -1, { .flags.inex : false } }; } 431 // width must include room for null terminator 432 _Istream_Cstr wdi( unsigned int wd, char s[] ) { return (_Istream_Cstr)@{ s, { {0p}, wd, {.all : 0} } }; } 433 // read width does not include null terminator 434 _Istream_Cstr wdi( unsigned int wd, unsigned int rwd, char s[] ) { 435 if ( wd <= rwd ) throw (cstring_length){ &cstring_length_vt }; 436 return (_Istream_Cstr)@{ s, { {0p}, rwd, {.flags.rwd : true} } }; 437 } 438 _Istream_Cstr skip( const char scanset[] ) { return (_Istream_Cstr)@{ 0p, { {scanset}, -1, {.all : 0} } }; } 439 _Istream_Cstr skip( unsigned int wd ) { return (_Istream_Cstr)@{ 0p, { {0p}, wd, {.all : 0} } }; } 440 _Istream_Cstr & getline( _Istream_Cstr & fmt, const char delimit = '\n' ) { 441 fmt.delimit[0] = delimit; fmt.delimit[1] = '\0'; fmt.flags.delimit = true; fmt.flags.inex = true; return fmt; } 404 442 _Istream_Cstr & incl( const char scanset[], _Istream_Cstr & fmt ) { fmt.scanset = scanset; fmt.flags.inex = false; return fmt; } 405 _Istream_Cstr excl( const char scanset[], char * s ) { return (_Istream_Cstr){ s, scanset, -1, { .flags.inex : true } }; }406 443 _Istream_Cstr & excl( const char scanset[], _Istream_Cstr & fmt ) { fmt.scanset = scanset; fmt.flags.inex = true; return fmt; } 407 _Istream_Cstr ignore( char s[] ) { return (_Istream_Cstr)@{ s, 0p, -1, { .flags.ignore : true} }; }444 _Istream_Cstr ignore( char s[] ) { return (_Istream_Cstr)@{ s, { {0p}, -1, {.flags.ignore : true} } }; } 408 445 _Istream_Cstr & ignore( _Istream_Cstr & fmt ) { fmt.flags.ignore = true; return fmt; } 409 _Istream_Cstr wdi( unsigned int w, char s[] ) { return (_Istream_Cstr)@{ s, 0p, w, { .all : 0 } }; }410 _Istream_Cstr & wdi( unsigned int w, _Istream_Cstr & fmt ) { fmt.wd = w; return fmt; }411 446 } // distribution 412 447 forall( istype & | basic_istream( istype ) ) { 413 448 istype & ?|?( istype & is, _Istream_Cstr f ); 414 void ?|?( istype & is, _Istream_Cstr f);449 ISTYPE_VOID( _Istream_Cstr ); 415 450 } 416 451 … … 425 460 forall( istype & | basic_istream( istype ) ) { 426 461 istype & ?|?( istype & is, _Istream_Char f ); 427 void ?|?( istype & is, _Istream_Char f);462 ISTYPE_VOID( _Istream_Char ); 428 463 } 429 464 … … 435 470 }; // _Istream_Manip 436 471 437 #define I nputFMTDecl( T ) \472 #define INPUT_FMT_DECL( T ) \ 438 473 static inline { \ 439 474 _Istream_Manip(T) ignore( const T & val ) { return (_Istream_Manip(T))@{ (T &)val, -1, true }; } \ 440 475 _Istream_Manip(T) & ignore( _Istream_Manip(T) & fmt ) { fmt.ignore = true; return fmt; } \ 441 _Istream_Manip(T) wdi( unsigned int w , T & val ) { return (_Istream_Manip(T))@{ val, w, false }; } \442 _Istream_Manip(T) & wdi( unsigned int w , _Istream_Manip(T) & fmt ) { fmt.wd = w; return fmt; } \476 _Istream_Manip(T) wdi( unsigned int wd, T & val ) { return (_Istream_Manip(T))@{ val, wd, false }; } \ 477 _Istream_Manip(T) & wdi( unsigned int wd, _Istream_Manip(T) & fmt ) { fmt.wd = wd; return fmt; } \ 443 478 } /* distribution */ \ 444 479 forall( istype & | basic_istream( istype ) ) { \ 445 480 istype & ?|?( istype & is, _Istream_Manip(T) f ); \ 446 void ?|?( istype & is, _Istream_Manip(T) f); \481 ISTYPE_VOID( _Istream_Manip(T) ); \ 447 482 } // ?|? 448 483 449 InputFMTDecl( signed char ) 450 InputFMTDecl( unsigned char ) 451 InputFMTDecl( signed short int ) 452 InputFMTDecl( unsigned short int ) 453 InputFMTDecl( signed int ) 454 InputFMTDecl( unsigned int ) 455 InputFMTDecl( signed long int ) 456 InputFMTDecl( unsigned long int ) 457 InputFMTDecl( signed long long int ) 458 InputFMTDecl( unsigned long long int ) 459 460 InputFMTDecl( float ) 461 InputFMTDecl( double ) 462 InputFMTDecl( long double ) 463 464 InputFMTDecl( float _Complex ) 465 InputFMTDecl( double _Complex ) 466 InputFMTDecl( long double _Complex ) 467 484 INPUT_FMT_DECL( signed char ) 485 INPUT_FMT_DECL( unsigned char ) 486 INPUT_FMT_DECL( signed short int ) 487 INPUT_FMT_DECL( unsigned short int ) 488 INPUT_FMT_DECL( signed int ) 489 INPUT_FMT_DECL( unsigned int ) 490 INPUT_FMT_DECL( signed long int ) 491 INPUT_FMT_DECL( unsigned long int ) 492 INPUT_FMT_DECL( signed long long int ) 493 INPUT_FMT_DECL( unsigned long long int ) 494 495 INPUT_FMT_DECL( float ) 496 INPUT_FMT_DECL( double ) 497 INPUT_FMT_DECL( long double ) 498 499 INPUT_FMT_DECL( float _Complex ) 500 INPUT_FMT_DECL( double _Complex ) 501 INPUT_FMT_DECL( long double _Complex ) 468 502 469 503 // *********************************** time *********************************** 470 471 504 472 505 #include <time_t.hfa> // Duration (constructors) / Time (constructors) … … 474 507 forall( ostype & | ostream( ostype ) ) { 475 508 ostype & ?|?( ostype & os, Duration dur ); 476 void ?|?( ostype & os, Duration dur);509 OSTYPE_VOID( Duration ); 477 510 ostype & ?|?( ostype & os, Time time ); 478 void ?|?( ostype & os, Time time );511 OSTYPE_VOID( Time ); 479 512 } // distribution 480 513 -
libcfa/src/parseargs.cfa
r92355883 r2a301ff 230 230 } 231 231 232 void print_args_usage(cfa_option options[], size_t opt_count, const char * usage, bool error) __attribute__ ((noreturn)) {232 void print_args_usage(cfa_option options[], const size_t opt_count, const char * usage, bool error) __attribute__ ((noreturn)) { 233 233 const array( cfa_option, opt_count ) & arr = (const array( cfa_option, opt_count ) &) *options; 234 234 usage(cfa_args_argv[0], arr, usage, error ? stderr : stdout); 235 235 } 236 236 237 void print_args_usage(int , char * argv[], cfa_option options[], size_t opt_count, const char * usage, bool error) __attribute__ ((noreturn)) {237 void print_args_usage(int , char * argv[], cfa_option options[], const size_t opt_count, const char * usage, bool error) __attribute__ ((noreturn)) { 238 238 const array( cfa_option, opt_count ) & arr = (const array( cfa_option, opt_count ) &) *options; 239 239 usage(argv[0], arr, usage, error ? stderr : stdout); -
libcfa/src/parseconfig.cfa
r92355883 r2a301ff 16 16 #pragma GCC visibility push(default) 17 17 18 18 19 // *********************************** exceptions *********************************** 19 20 20 21 // TODO: Add names of missing config entries to exception (see further below)22 vtable(Missing_Config_Entries) Missing_Config_Entries_vt;23 21 24 22 [ void ] ?{}( & Missing_Config_Entries this, unsigned int num_missing ) { … … 29 27 // TODO: use string interface when it's ready (and implement exception msg protocol) 30 28 [ void ] msg( * Missing_Config_Entries ex ) { 31 serr | "The config file is missing " | ex->num_missing | "entr" | sepOff| (ex->num_missing == 1 ? "y." : "ies.");29 serr | "The config file is missing " | ex->num_missing | "entr" | nosep | (ex->num_missing == 1 ? "y." : "ies."); 32 30 } // msg 33 31 34 35 vtable(Parse_Failure) Parse_Failure_vt;36 32 37 33 [ void ] ?{}( & Parse_Failure this, [] char failed_key, [] char failed_value ) { … … 54 50 } 55 51 56 57 vtable(Validation_Failure) Validation_Failure_vt;58 52 59 53 [ void ] ?{}( & Validation_Failure this, [] char failed_key, [] char failed_value ) { … … 112 106 113 107 114 static [ bool ] comments( & ifstream in, [] char name ) {108 static [ bool ] comments( & ifstream in, size_t size, [] char name ) { 115 109 while () { 116 in | name;110 in | wdi( size, name ); 117 111 if ( eof( in ) ) return true; 118 112 if ( name[0] != '#' ) return false; … … 136 130 // NOTE: Must add check to see if already read in value for this key, 137 131 // once we switch to using hash table as intermediate storage 138 if ( comments( in, key ) ) break;// eof ?139 in | value;132 if ( comments( in, 64, key ) ) break; // eof ? 133 in | wdi( 256, value ); 140 134 141 135 add_kv_pair( *kv_pairs, key, value ); -
libcfa/src/parseconfig.hfa
r92355883 r2a301ff 2 2 3 3 #include <math.trait.hfa> 4 #include <Exception.hfa> 4 5 5 6 … … 62 63 63 64 64 exception Missing_Config_Entries { 65 ExceptionDecl( Missing_Config_Entries, 65 66 unsigned int num_missing; 66 };67 ); 67 68 68 69 [ void ] msg( * Missing_Config_Entries ex ); 69 70 70 exception Parse_Failure { 71 ExceptionDecl( Parse_Failure, 71 72 * char failed_key; 72 73 * char failed_value; 73 };74 ); 74 75 75 76 [ void ] msg( * Parse_Failure ex ); 76 77 77 exception Validation_Failure { 78 ExceptionDecl( Validation_Failure, 78 79 * char failed_key; 79 80 * char failed_value; 80 };81 ); 81 82 82 83 [ void ] msg( * Validation_Failure ex ); -
libcfa/src/rational.cfa
r92355883 r2a301ff 10 10 // Created On : Wed Apr 6 17:54:28 2016 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Mon Jun 5 22:49:06202313 // Update Count : 19 612 // Last Modified On : Tue Jul 18 11:07:10 2023 13 // Update Count : 197 14 14 // 15 15 … … 206 206 return os | r.numerator | '/' | r.denominator; 207 207 } // ?|? 208 209 void ?|?( ostype & os, rational(T) r ) { 210 (ostype &)(os | r); ends( os ); 211 } // ?|? 208 OSTYPE_VOID_IMPL( rational(T) ) 212 209 } // distribution 213 210 } // distribution -
libcfa/src/rational.hfa
r92355883 r2a301ff 12 12 // Created On : Wed Apr 6 17:56:25 2016 13 13 // Last Modified By : Peter A. Buhr 14 // Last Modified On : Mon Jun 5 22:49:05202315 // Update Count : 1 1914 // Last Modified On : Tue Jul 18 11:08:24 2023 15 // Update Count : 121 16 16 // 17 17 … … 78 78 forall( ostype & | ostream( ostype ) | { ostype & ?|?( ostype &, T ); } ) { 79 79 ostype & ?|?( ostype &, rational(T) ); 80 void ?|?( ostype &,rational(T) );80 OSTYPE_VOID( rational(T) ); 81 81 } // distribution 82 82 } // distribution -
libcfa/src/stdlib.cfa
r92355883 r2a301ff 10 10 // Created On : Thu Jan 28 17:10:29 2016 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Thu Feb 16 16:31:34202313 // Update Count : 6 3312 // Last Modified On : Mon Aug 14 18:22:36 2023 13 // Update Count : 642 14 14 // 15 15 … … 65 65 //--------------------------------------- 66 66 67 float _Complex strto( const char sptr[], char ** eptr ) { 67 forall( T | { T strto( const char sptr[], char * eptr[], int ); } ) 68 T convert( const char sptr[] ) { 69 char * eptr; 70 errno = 0; // reset 71 T val = strto( sptr, &eptr, 10 ); // attempt conversion 72 if ( errno == ERANGE ) throw ExceptionInst( out_of_range ); 73 if ( eptr == sptr || // conversion failed, no characters generated 74 *eptr != '\0' ) throw ExceptionInst( invalid_argument ); // not at end of str ? 75 return val; 76 } // convert 77 78 float _Complex strto( const char sptr[], char * eptr[] ) { 68 79 float re, im; 69 80 char * eeptr; … … 76 87 } // strto 77 88 78 double _Complex strto( const char sptr[], char * * eptr) {89 double _Complex strto( const char sptr[], char * eptr[] ) { 79 90 double re, im; 80 91 char * eeptr; … … 87 98 } // strto 88 99 89 long double _Complex strto( const char sptr[], char * * eptr) {100 long double _Complex strto( const char sptr[], char * eptr[] ) { 90 101 long double re, im; 91 102 char * eeptr; -
libcfa/src/stdlib.hfa
r92355883 r2a301ff 10 10 // Created On : Thu Jan 28 17:12:35 2016 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Thu Feb 2 11:30:04202313 // Update Count : 7 6612 // Last Modified On : Mon Aug 14 18:19:12 2023 13 // Update Count : 777 14 14 // 15 15 … … 19 19 #include "bits/align.hfa" // libAlign 20 20 #include "bits/random.hfa" // prng 21 #include <Exception.hfa> 22 #include <heap.hfa> 21 23 22 24 #include <stdlib.h> // *alloc, strto*, ato* 23 #include <heap.hfa> 24 25 #include <errno.h> 25 26 26 27 // Reduce includes by explicitly defining these routines. … … 294 295 295 296 static inline { 296 int strto( const char sptr[], char ** eptr, int base ) { return (int)strtol( sptr, eptr, base ); } 297 unsigned int strto( const char sptr[], char ** eptr, int base ) { return (unsigned int)strtoul( sptr, eptr, base ); } 298 long int strto( const char sptr[], char ** eptr, int base ) { return strtol( sptr, eptr, base ); } 299 unsigned long int strto( const char sptr[], char ** eptr, int base ) { return strtoul( sptr, eptr, base ); } 300 long long int strto( const char sptr[], char ** eptr, int base ) { return strtoll( sptr, eptr, base ); } 301 unsigned long long int strto( const char sptr[], char ** eptr, int base ) { return strtoull( sptr, eptr, base ); } 302 303 float strto( const char sptr[], char ** eptr ) { return strtof( sptr, eptr ); } 304 double strto( const char sptr[], char ** eptr ) { return strtod( sptr, eptr ); } 305 long double strto( const char sptr[], char ** eptr ) { return strtold( sptr, eptr ); } 306 } // distribution 307 308 float _Complex strto( const char sptr[], char ** eptr ); 309 double _Complex strto( const char sptr[], char ** eptr ); 310 long double _Complex strto( const char sptr[], char ** eptr ); 297 int strto( const char sptr[], char * eptr[], int base ) { return (int)strtol( sptr, eptr, base ); } 298 unsigned int strto( const char sptr[], char * eptr[], int base ) { return (unsigned int)strtoul( sptr, eptr, base ); } 299 long int strto( const char sptr[], char * eptr[], int base ) { return strtol( sptr, eptr, base ); } 300 unsigned long int strto( const char sptr[], char * eptr[], int base ) { return strtoul( sptr, eptr, base ); } 301 long long int strto( const char sptr[], char * eptr[], int base ) { return strtoll( sptr, eptr, base ); } 302 unsigned long long int strto( const char sptr[], char * eptr[], int base ) { return strtoull( sptr, eptr, base ); } 303 304 float strto( const char sptr[], char * eptr[] ) { return strtof( sptr, eptr ); } 305 double strto( const char sptr[], char * eptr[] ) { return strtod( sptr, eptr ); } 306 long double strto( const char sptr[], char * eptr[] ) { return strtold( sptr, eptr ); } 307 } // distribution 308 309 float _Complex strto( const char sptr[], char * eptr[] ); 310 double _Complex strto( const char sptr[], char * eptr[] ); 311 long double _Complex strto( const char sptr[], char * eptr[] ); 312 313 ExceptionDecl( out_of_range ); 314 ExceptionDecl( invalid_argument ); 315 316 forall( T | { T strto( const char sptr[], char * eptr[], int ); } ) 317 T convert( const char sptr[] ); 311 318 312 319 static inline { … … 454 461 } // distribution 455 462 463 // Set default random-generator size. 464 #if defined( __x86_64__ ) || defined( __aarch64__ ) // 64-bit architecture 465 #define PRNG PRNG64 466 #else // 32-bit architecture 467 #define PRNG PRNG32 468 #endif // __x86_64__ 469 456 470 // Concurrent Pseudo Random-Number Generator : generate repeatable sequence of values that appear random. 457 471 // -
libcfa/src/strstream.cfa
r92355883 r2a301ff 10 10 // Created On : Thu Apr 22 22:24:35 2021 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Sun Oct 10 16:13:20 202113 // Update Count : 1 0112 // Last Modified On : Fri Aug 18 10:42:49 2023 13 // Update Count : 112 14 14 // 15 15 … … 32 32 33 33 // private 34 inline bool getNL$( ostrstream & os ) { return os.sawNL$; } 35 inline bool setNL$( ostrstream & os, bool state ) { bool temp = os.sawNL$; os.sawNL$ = state; return temp; } 36 inline bool getANL$( ostrstream & os ) { return os.nlOnOff$; } 37 inline bool setANL$( ostrstream & os, bool state ) { bool temp = os.nlOnOff$; os.nlOnOff$ = state; return temp; } 34 38 inline bool sepPrt$( ostrstream & os ) { setNL$( os, false ); return os.sepOnOff$; } 35 39 inline void sepReset$( ostrstream & os ) { os.sepOnOff$ = os.sepDefault$; } … … 37 41 inline const char * sepGetCur$( ostrstream & os ) { return os.sepCur$; } 38 42 inline void sepSetCur$( ostrstream & os, const char sepCur[] ) { os.sepCur$ = sepCur; } 39 inline bool getNL$( ostrstream & os ) { return os.sawNL$; }40 inline void setNL$( ostrstream & os, bool state ) { os.sawNL$ = state; }41 inline bool getANL$( ostrstream & os ) { return os.nlOnOff$; }42 43 inline bool getPrt$( ostrstream & os ) { return os.prt$; } 43 inline void setPrt$( ostrstream & os, bool state ) { os.prt$ = state; }44 inline bool setPrt$( ostrstream & os, bool state ) { bool temp = os.prt$; os.prt$ = state; return temp; } 44 45 45 46 // public 47 void nlOn( ostrstream & os ) { os.nlOnOff$ = true; } 48 void nlOff( ostrstream & os ) { os.nlOnOff$ = false; } 49 46 50 void ?{}( ostrstream & os, char buf[], size_t size ) { 47 51 os.buf$ = buf; … … 58 62 } // ?{} 59 63 60 void sep On( ostrstream & os ) { os.sepOnOff$ = ! getNL$( os ); }61 void sepOff( ostrstream & os ) { os.sepOnOff$ = false; }64 void sep( ostrstream & os ) { os.sepOnOff$ = ! getNL$( os ); } 65 void nosep( ostrstream & os ) { os.sepOnOff$ = false; } 62 66 63 bool sepDisable( ostrstream & os ) { 67 bool sepOn( ostrstream & os ) { 68 bool temp = os.sepDefault$; 69 os.sepDefault$ = true; 70 if ( os.sepOnOff$ ) sepReset$( os ); // start of line ? 71 return temp; 72 } // sepOn 73 74 bool sepOff( ostrstream & os ) { 64 75 bool temp = os.sepDefault$; 65 76 os.sepDefault$ = false; 66 77 sepReset$( os ); 67 78 return temp; 68 } // sepDisable 69 70 bool sepEnable( ostrstream & os ) { 71 bool temp = os.sepDefault$; 72 os.sepDefault$ = true; 73 if ( os.sepOnOff$ ) sepReset$( os ); // start of line ? 74 return temp; 75 } // sepEnable 76 77 void nlOn( ostrstream & os ) { os.nlOnOff$ = true; } 78 void nlOff( ostrstream & os ) { os.nlOnOff$ = false; } 79 } // sepOff 79 80 80 81 const char * sepGet( ostrstream & os ) { return os.separator$; } … … 132 133 // private 133 134 bool getANL$( istrstream & is ) { return is.nlOnOff$; } 135 bool setANL$( istrstream & is, bool state ) { bool temp = is.nlOnOff$; is.nlOnOff$ = state; return temp; } 134 136 135 137 // public -
libcfa/src/strstream.hfa
r92355883 r2a301ff 10 10 // Created On : Thu Apr 22 22:20:59 2021 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Sun Oct 10 10:14:22 202113 // Update Count : 4712 // Last Modified On : Fri Aug 18 10:41:14 2023 13 // Update Count : 55 14 14 // 15 15 … … 47 47 void sepSetCur$( ostrstream &, const char [] ); 48 48 bool getNL$( ostrstream & ); 49 voidsetNL$( ostrstream &, bool );49 bool setNL$( ostrstream &, bool ); 50 50 bool getANL$( ostrstream & ); 51 bool setANL$( ostrstream &, bool ); 51 52 bool getPrt$( ostrstream & ); 52 voidsetPrt$( ostrstream &, bool );53 bool setPrt$( ostrstream &, bool ); 53 54 54 55 // public 55 void sepOn( ostrstream & );56 void sepOff( ostrstream & );57 bool sepDisable( ostrstream & );58 bool sepEnable( ostrstream & );59 56 void nlOn( ostrstream & ); 60 57 void nlOff( ostrstream & ); 61 58 59 void sep( ostrstream & ); 60 void nosep( ostrstream & ); 61 bool sepOn( ostrstream & ); 62 bool sepOff( ostrstream & ); 62 63 const char * sepGet( ostrstream & ); 63 64 void sepSet( ostrstream &, const char [] ); … … 87 88 // private 88 89 bool getANL$( istrstream & ); 90 bool setANL$( istrstream &, bool ); 89 91 90 92 // public -
libcfa/src/time.cfa
r92355883 r2a301ff 10 10 // Created On : Tue Mar 27 13:33:14 2018 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Tue Feb 4 08:24:18 202013 // Update Count : 7 012 // Last Modified On : Tue Jul 18 10:55:01 2023 13 // Update Count : 71 14 14 // 15 15 … … 43 43 return os; 44 44 } // ?|? 45 46 void ?|?( ostype & os, Duration dur ) with( dur ) { 47 (ostype &)(os | dur); ends( os ); 48 } // ?|? 45 OSTYPE_VOID_IMPL( Duration ) 49 46 } // distribution 50 47 … … 155 152 return os; 156 153 } // ?|? 157 158 void ?|?( ostype & os, Time time ) with( time ) { 159 (ostype &)(os | time); ends( os ); 160 } // ?|? 154 OSTYPE_VOID_IMPL( Time ) 161 155 } // distribution 162 156 -
libcfa/src/vec/vec.hfa
r92355883 r2a301ff 79 79 } 80 80 81 trait dottable(V, T) { 81 forall(V, T) 82 trait dottable { 82 83 T dot(V, V); 83 84 }; -
libcfa/src/vec/vec2.hfa
r92355883 r2a301ff 283 283 return os | '<' | x | ',' | y | '>'; 284 284 } 285 void ?|?(ostype & os, vec2(T) v ) with (v) { 286 (ostype &)(os | v); ends(os); 287 } 285 OSTYPE_VOID_IMPL( vec2(T) ) 288 286 } -
libcfa/src/vec/vec3.hfa
r92355883 r2a301ff 292 292 return os | '<' | x | ',' | y | ',' | z | '>'; 293 293 } 294 void ?|?(ostype & os, vec3(T) v ) with (v) { 295 (ostype &)(os | v); ends(os); 296 } 294 OSTYPE_VOID_IMPL( vec3(T) ) 297 295 } -
libcfa/src/vec/vec4.hfa
r92355883 r2a301ff 287 287 return os | '<' | x | ',' | y | ',' | z | ',' | w | '>'; 288 288 } 289 void ?|?(ostype & os, vec4(T) v ) with (v) { 290 (ostype &)(os | v); ends(os); 291 } 289 OSTYPE_VOID_IMPL( vec4(T) ) 292 290 } 293 291 -
libcfa/src/virtual_dtor.hfa
r92355883 r2a301ff 1 // inline this structure to have a virtual dtor. 1 #pragma once 2 3 // inline virtual_dtor to have a virtual dtor. 2 4 // when using this, delete() is also virtual and will be called on the right address 3 5 // using free() directly on polymorphic types may result in unaligned memory deallocation … … 8 10 // given struct A { inline virtual_dtor; } and struct B { inline virtual_dtor; } 9 11 // struct C { inline A; inline B; } will result in undefined behaviour 10 11 12 struct virtual_dtor { 12 13 void (*__virtual_dtor_ptr)(virtual_dtor &);
Note:
See TracChangeset
for help on using the changeset viewer.