Changeset 2a301ff for libcfa


Ignore:
Timestamp:
Aug 31, 2023, 11:31:15 PM (2 years ago)
Author:
JiadaL <j82liang@…>
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.
Message:

Resolve conflict

Location:
libcfa
Files:
2 added
1 deleted
52 edited
17 moved

Legend:

Unmodified
Added
Removed
  • libcfa/prelude/bootloader.cf

    r92355883 r2a301ff  
    1 extern "C" { static inline int invoke_main(int argc, char* argv[], char* envp[]); }
     1extern "C" { static inline int invoke_main( int argc, char * argv[], char * envp[]); }
    22int cfa_args_argc;
    33char ** cfa_args_argv;
     
    55__attribute__((weak)) extern int cfa_main_returned;
    66
    7 int main(int argc, char* argv[], char* envp[]) {
     7int main( int argc, char * argv[], char * envp[] ) {
    88        cfa_args_argc = argc;
    99        cfa_args_argv = argv;
    1010        cfa_args_envp = envp;
    1111        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;
    1313        return ret;
    1414}
  • libcfa/prelude/builtins.c

    r92355883 r2a301ff  
    132132} // distribution
    133133
    134 #define __CFA_BASE_COMP_1__() if ( x == 1 ) return 1
    135 #define __CFA_BASE_COMP_2__() if ( x == 2 ) return x << (y - 1)
    136 #define __CFA_EXP_OVERFLOW__() if ( y >= sizeof(y) * CHAR_BIT ) return 0
    137 
    138134#define __CFA_EXP__() \
    139135        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        ) \
    143141        typeof(x) op = 1;                                                                       /* accumulate odd product */ \
    144142        for ( ; y > 1; y >>= 1 ) {                                                      /* squaring exponentiation, O(log2 y) */ \
     
    147145        } \
    148146        return x * op
     147#define __CFA_EXP_INT__(...) __VA_ARGS__
    149148
    150149static inline {
     
    158157} // distribution
    159158
    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__(...)
    166161
    167162static inline forall( OT | { void ?{}( OT & this, one_t ); OT ?*?( OT, OT ); } ) {
     
    171166} // distribution
    172167
    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__
    176170
    177171static inline {
  • libcfa/prelude/prelude-gen.cc

    r92355883 r2a301ff  
    159159int main() {
    160160        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;
    162162
    163163        cout << "//////////////////////////" << endl;
  • libcfa/src/Makefile.am

    r92355883 r2a301ff  
    1111## Created On       : Sun May 31 08:54:01 2015
    1212## Last Modified By : Peter A. Buhr
    13 ## Last Modified On : Thu May 25 15:20:04 2023
    14 ## Update Count     : 259
     13## Last Modified On : Wed Aug 30 21:22:45 2023
     14## Update Count     : 263
    1515###############################################################################
    1616
     
    4040if BUILDLIB
    4141inst_headers_nosrc = \
     42        Exception.hfa \
    4243        bitmanip.hfa \
    4344        clock.hfa \
     
    5152        bits/algorithm.hfa \
    5253        bits/align.hfa \
    53         bits/containers.hfa \
     54        bits/collections.hfa \
    5455        bits/debug.hfa \
    5556        bits/defs.hfa \
     
    6263        concurrency/iofwd.hfa \
    6364        concurrency/barrier.hfa \
    64         containers/array.hfa \
    65         containers/list.hfa \
    66         containers/lockfree.hfa \
    67         containers/string_sharectx.hfa \
    68         containers/vector2.hfa \
     65        collections/array.hfa \
     66        collections/list.hfa \
     67        collections/lockfree.hfa \
     68        collections/string_sharectx.hfa \
     69        collections/vector2.hfa \
    6970        vec/vec.hfa \
    7071        vec/vec2.hfa \
     
    8889        bits/weakso_locks.hfa \
    8990        algorithms/range_iterator.hfa \
    90         containers/maybe.hfa \
    91         containers/pair.hfa \
    92         containers/result.hfa \
    93         containers/string.hfa \
    94         containers/string_res.hfa \
    95         containers/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 \
    9697        device/cpu.hfa
    9798
  • libcfa/src/bits/algorithm.hfa

    r92355883 r2a301ff  
    99// Author           : Thierry Delisle
    1010// Created On       : Mon Oct 30 13:37:34 2017
    11 // Last Modified By : --
    12 // Last Modified On : --
    13 // Update Count     : 0
     11// Last Modified By : Peter A. Buhr
     12// Last Modified On : Sat Jul 22 08:25:29 2023
     13// Update Count     : 3
    1414//
    1515
     
    1717
    1818#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 );
     19forall( T | { int ?<?( T, T ); int ?>?( T, T ); } ) static inline void __libcfa_small_sort2( T * arr );
     20forall( T | { int ?<?( T, T ); int ?>?( T, T ); } ) static inline void __libcfa_small_sort3( T * arr );
     21forall( T | { int ?<?( T, T ); int ?>?( T, T ); } ) static inline void __libcfa_small_sort4( T * arr );
     22forall( T | { int ?<?( T, T ); int ?>?( T, T ); } ) static inline void __libcfa_small_sort5( T * arr );
     23forall( T | { int ?<?( T, T ); int ?>?( T, T ); } ) static inline void __libcfa_small_sort6( T * arr );
     24forall( T | { int ?<?( T, T ); int ?>?( T, T ); } ) static inline void __libcfa_small_sortN( T * arr, size_t dim );
    2525
    26 forall( T | {  int ?<?( T, T ); int ?>?( T, T ); } )
     26forall( T | { int ?<?( T, T ); int ?>?( T, T ); } )
    2727static inline void __libcfa_small_sort( T * arr, size_t dim ) {
    2828        switch( dim ) {
     
    4141#define SWAP(x,y) { T a = min(arr[x], arr[y]); T b = max(arr[x], arr[y]); arr[x] = a; arr[y] = b;}
    4242
    43 forall( T | {  int ?<?( T, T ); int ?>?( T, T ); } )
     43forall( T | { int ?<?( T, T ); int ?>?( T, T ); } )
    4444static inline void __libcfa_small_sort2( T * arr ) {
    4545        SWAP(0, 1);
    4646}
    4747
    48 forall( T | {  int ?<?( T, T ); int ?>?( T, T ); } )
     48forall( T | { int ?<?( T, T ); int ?>?( T, T ); } )
    4949static inline void __libcfa_small_sort3( T * arr ) {
    5050        SWAP(1, 2);
     
    5353}
    5454
    55 forall( T | {  int ?<?( T, T ); int ?>?( T, T ); } )
     55forall( T | { int ?<?( T, T ); int ?>?( T, T ); } )
    5656static inline void __libcfa_small_sort4( T * arr ) {
    5757        SWAP(0, 1);
     
    6262}
    6363
    64 forall( T | {  int ?<?( T, T ); int ?>?( T, T ); } )
     64forall( T | { int ?<?( T, T ); int ?>?( T, T ); } )
    6565static inline void __libcfa_small_sort5( T * arr ) {
    6666        SWAP(0, 1);
     
    7575}
    7676
    77 forall( T | {  int ?<?( T, T ); int ?>?( T, T ); } )
     77forall( T | { int ?<?( T, T ); int ?>?( T, T ); } )
    7878static inline void __libcfa_small_sort6( T * arr ) {
    7979        SWAP(1, 2);
     
    9191}
    9292
    93 forall( T | {  int ?<?( T, T ); int ?>?( T, T ); } )
     93forall( T | { int ?<?( T, T ); int ?>?( T, T ); } )
    9494static 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 ) {
    9796                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--) {
    9999                        arr[j] = arr[j-1];
    100100                }
     
    175175
    176176static 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;
    180180                for (j = i; j >= 1 && tmp < arr[j-1]; j--) {
    181181                        arr[j] = arr[j-1];
  • libcfa/src/bits/collections.hfa

    r92355883 r2a301ff  
    55// file "LICENCE" distributed with Cforall.
    66//
    7 // bits/containers.hfa -- Intrusive generic containers.hfa
     7// bits/collections.hfa -- Intrusive generic collections
    88//
    99// Author           : Thierry Delisle
    1010// Created On       : Tue Oct 31 16:38:50 2017
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Thu Feb  2 11:33:08 2023
    13 // Update Count     : 29
     12// Last Modified On : Wed Aug 30 21:26:39 2023
     13// Update Count     : 30
    1414
    1515#pragma once
  • libcfa/src/bits/debug.cfa

    r92355883 r2a301ff  
    1010// Created On       : Thu Mar 30 12:30:01 2017
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Fri Apr 22 18:20:26 2022
    13 // Update Count     : 13
     12// Last Modified On : Sat Jul 22 08:17:27 2023
     13// Update Count     : 14
    1414//
    1515
     
    3333                        in_buffer += count;
    3434
    35                         for ( ;; ) {
     35                        for () {
    3636                                retcode = write( fd, in_buffer, len - count );
    3737
  • libcfa/src/bits/queue.hfa

    r92355883 r2a301ff  
    9191                        T * prev = 0p;
    9292                        T * curr = (T *)root;
    93                         for ( ;; ) {
     93                        for () {
    9494                                if ( &n == curr ) {                                             // found => remove
    9595                                        if ( (T *)root == &n ) {
  • libcfa/src/bits/weakso_locks.cfa

    r92355883 r2a301ff  
    3030bool register_select( blocking_lock & this, select_node & node ) { return false; }
    3131bool unregister_select( blocking_lock & this, select_node & node ) { return false; }
    32 void on_selected( blocking_lock & this, select_node & node ) {}
     32bool on_selected( blocking_lock & this, select_node & node ) { return true; }
    3333
  • libcfa/src/bits/weakso_locks.hfa

    r92355883 r2a301ff  
    2020#include "bits/locks.hfa"
    2121#include "bits/sequence.hfa"
    22 #include "bits/containers.hfa"
    23 #include "containers/list.hfa"
     22#include "bits/collections.hfa"
     23#include "collections/list.hfa"
    2424
    2525struct select_node;
     
    6262bool register_select( blocking_lock & this, select_node & node ) OPTIONAL_THREAD;
    6363bool unregister_select( blocking_lock & this, select_node & node ) OPTIONAL_THREAD;
    64 void on_selected( blocking_lock & this, select_node & node ) OPTIONAL_THREAD;
     64bool on_selected( blocking_lock & this, select_node & node ) OPTIONAL_THREAD;
     65blocking_lock __CFA_select_get_type( blocking_lock this ) OPTIONAL_THREAD;
    6566
    6667//----------
     
    8081static inline bool   register_select( multiple_acquisition_lock & this, select_node & node ) { return register_select( (blocking_lock &)this, node ); }
    8182static 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 ); }
     83static inline bool   on_selected( multiple_acquisition_lock & this, select_node & node ) { return on_selected( (blocking_lock &)this, node ); }
     84multiple_acquisition_lock __CFA_select_get_type( multiple_acquisition_lock this );
  • libcfa/src/collections/array.hfa

    r92355883 r2a301ff  
    247247
    248248// desired:
    249 // trait ar(A &, Tv &, [N]) {
     249// forall(A &, Tv &, [N])
     250// trait ar {
    250251//     Tv& ?[?]( A&, zero_t );
    251252//     Tv& ?[?]( A&, one_t  );
  • libcfa/src/collections/maybe.cfa

    r92355883 r2a301ff  
    1010// Created On       : Wed May 24 15:40:00 2017
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Sun Feb 17 11:22:03 2019
    13 // Update Count     : 3
     12// Last Modified On : Wed Aug 30 21:26:55 2023
     13// Update Count     : 4
    1414//
    1515
    16 #include <containers/maybe.hfa>
     16#include <collections/maybe.hfa>
    1717#include <assert.h>
    1818
  • libcfa/src/collections/pair.cfa

    r92355883 r2a301ff  
    66// Author           : Aaron Moss
    77// Created On       : Wed Apr 12 15:32:00 2017
    8 // Last Modified By : Aaron Moss
    9 // Last Modified On : Wed Apr 12 15:32:00 2017
    10 // Update Count     : 1
     8// Last Modified By : Peter A. Buhr
     9// Last Modified On : Wed Aug 30 21:27:12 2023
     10// Update Count     : 2
    1111//
    1212
    13 #include <containers/pair.hfa>
     13#include <collections/pair.hfa>
    1414
    1515forall(R, S
  • libcfa/src/collections/result.cfa

    r92355883 r2a301ff  
    1010// Created On       : Wed May 24 15:40:00 2017
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Sun Feb 17 11:24:04 2019
    13 // Update Count     : 3
     12// Last Modified On : Wed Aug 30 21:27:22 2023
     13// Update Count     : 4
    1414//
    1515
    16 #include <containers/result.hfa>
     16#include <collections/result.hfa>
    1717#include <assert.h>
    1818
  • libcfa/src/collections/string.cfa

    r92355883 r2a301ff  
    99// Author           : Michael L. Brooks
    1010// Created On       : Fri Sep 03 11:00:00 2021
    11 // Last Modified By : Michael L. Brooks
    12 // Last Modified On : Fri Sep 03 11:00:00 2021
    13 // 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
    1414//
    1515
     
    5555}
    5656
    57 void ?{}( string & this, const char* buffer, size_t bsize) {
     57void ?{}( string & this, const char * buffer, size_t bsize) {
    5858    (this.inner) { malloc() };
    5959    ?{}( *this.inner, buffer, bsize );
     
    100100
    101101////////////////////////////////////////////////////////
    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
     104ofstream & ?|?( ofstream & out, const string & this ) {
     105    return out | (*this.inner); // print internal string_res
     106}
     107
     108void ?|?( ofstream & out, const string & this ) {
     109    (ofstream &)(out | (*this.inner)); ends( out );
     110}
     111
     112ifstream & ?|?(ifstream & in, string & this) {
     113    return in | (*this.inner); // read to internal string_res
     114}
     115
     116void ?|?( ifstream & in, string & this ) {
     117    (ifstream &)(in | this); ends( in );
     118}
     119
     120ifstream & ?|?( 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
     160void ?|?( ifstream & in, _Istream_str f ) {
     161    (ifstream &)(in | f); ends( in );
    110162}
    111163
     
    118170}
    119171
     172string ?()( string & this, size_t start ) {
     173    string ret = { *this.inner, start, size( this ) };
     174    return ret`shareEdits;
     175}
     176
    120177////////////////////////////////////////////////////////
    121178// Comparison
    122179
    123 bool ?==?(const string &s, const string &other) {
     180bool ?==?(const string & s, const string & other) {
    124181    return *s.inner == *other.inner;
    125182}
    126183
    127 bool ?!=?(const string &s, const string &other) {
     184bool ?!=?(const string & s, const string & other) {
    128185    return *s.inner != *other.inner;
    129186}
    130187
    131 bool ?==?(const string &s, const char* other) {
     188bool ?==?(const string & s, const char * other) {
    132189    return *s.inner == other;
    133190}
    134191
    135 bool ?!=?(const string &s, const char* other) {
     192bool ?!=?(const string & s, const char * other) {
    136193    return *s.inner != other;
    137194}
     
    140197// Getter
    141198
    142 size_t size(const string &s) {
     199size_t size(const string & s) {
    143200    return size( * s.inner );
    144201}
     
    147204// Concatenation
    148205
    149 void ?+=?(string &s, char other) {
     206void ?+=?(string & s, char other) {
    150207    (*s.inner) += other;
    151208}
    152209
    153 void ?+=?(string &s, const string &s2) {
     210void ?+=?(string & s, const string & s2) {
    154211    (*s.inner) += (*s2.inner);
    155212}
    156213
    157 void ?+=?(string &s, const char* other) {
     214void ?+=?(string & s, const char * other) {
    158215    (*s.inner) += other;
    159216}
    160217
    161 string ?+?(const string &s, char other) {
     218string ?+?(const string & s, char other) {
    162219    string ret = s;
    163220    ret += other;
     
    165222}
    166223
    167 string ?+?(const string &s, const string &s2) {
     224string ?+?(const string & s, const string & s2) {
    168225    string ret = s;
    169226    ret += s2;
     
    171228}
    172229
    173 string ?+?(const char* s1, const char* s2) {
     230string ?+?(const char * s1, const char * s2) {
    174231    string ret = s1;
    175232    ret += s2;
     
    177234}
    178235
    179 string ?+?(const string &s, const char* other) {
     236string ?+?(const string & s, const char * other) {
    180237    string ret = s;
    181238    ret += other;
     
    186243// Repetition
    187244
    188 string ?*?(const string &s, size_t factor) {
     245string ?*?(const string & s, size_t factor) {
    189246    string ret = "";
    190247    for (factor) ret += s;
     
    206263// Character access
    207264
    208 char ?[?](const string &s, size_t index) {
     265char ?[?](const string & s, size_t index) {
    209266    return (*s.inner)[index];
    210267}
    211268
    212 string ?[?](string &s, size_t index) {
     269string ?[?](string & s, size_t index) {
    213270    string ret = { *s.inner, index, index + 1 };
    214271    return ret`shareEdits;
     
    218275// Search
    219276
    220 bool contains(const string &s, char ch) {
     277bool contains(const string & s, char ch) {
    221278    return contains( *s.inner, ch );
    222279}
    223280
    224 int find(const string &s, char search) {
     281int find(const string & s, char search) {
    225282    return find( *s.inner, search );
    226283}
    227284
    228 int find(const string &s, const string &search) {
     285int find(const string & s, const string & search) {
    229286    return find( *s.inner, *search.inner );
    230287}
    231288
    232 int find(const string &s, const char* search) {
     289int find(const string & s, const char * search) {
    233290    return find( *s.inner, search);
    234291}
    235292
    236 int find(const string &s, const char* search, size_t searchsize) {
     293int find(const string & s, const char * search, size_t searchsize) {
    237294    return find( *s.inner, search, searchsize);
    238295}
    239296
    240 int findFrom(const string &s, size_t fromPos, char search) {
     297int findFrom(const string & s, size_t fromPos, char search) {
    241298    return findFrom( *s.inner, fromPos, search );
    242299}
    243300
    244 int findFrom(const string &s, size_t fromPos, const string &search) {
     301int findFrom(const string & s, size_t fromPos, const string & search) {
    245302    return findFrom( *s.inner, fromPos, *search.inner );
    246303}
    247304
    248 int findFrom(const string &s, size_t fromPos, const char* search) {
     305int findFrom(const string & s, size_t fromPos, const char * search) {
    249306    return findFrom( *s.inner, fromPos, search );
    250307}
    251308
    252 int findFrom(const string &s, size_t fromPos, const char* search, size_t searchsize) {
     309int findFrom(const string & s, size_t fromPos, const char * search, size_t searchsize) {
    253310    return findFrom( *s.inner, fromPos, search, searchsize );
    254311}
    255312
    256 bool includes(const string &s, const string &search) {
     313bool includes(const string & s, const string & search) {
    257314    return includes( *s.inner, *search.inner );
    258315}
    259316
    260 bool includes(const string &s, const char* search) {
     317bool includes(const string & s, const char * search) {
    261318    return includes( *s.inner, search );
    262319}
    263320
    264 bool includes(const string &s, const char* search, size_t searchsize) {
     321bool includes(const string & s, const char * search, size_t searchsize) {
    265322    return includes( *s.inner, search, searchsize );
    266323}
    267324
    268 bool startsWith(const string &s, const string &prefix) {
     325bool startsWith(const string & s, const string & prefix) {
    269326    return startsWith( *s.inner, *prefix.inner );
    270327}
    271328
    272 bool startsWith(const string &s, const char* prefix) {
     329bool startsWith(const string & s, const char * prefix) {
    273330    return startsWith( *s.inner, prefix );
    274331}
    275332
    276 bool startsWith(const string &s, const char* prefix, size_t prefixsize) {
     333bool startsWith(const string & s, const char * prefix, size_t prefixsize) {
    277334    return startsWith( *s.inner, prefix, prefixsize );
    278335}
    279336
    280 bool endsWith(const string &s, const string &suffix) {
     337bool endsWith(const string & s, const string & suffix) {
    281338    return endsWith( *s.inner, *suffix.inner );
    282339}
    283340
    284 bool endsWith(const string &s, const char* suffix) {
     341bool endsWith(const string & s, const char * suffix) {
    285342    return endsWith( *s.inner, suffix );
    286343}
    287344
    288 bool endsWith(const string &s, const char* suffix, size_t suffixsize) {
     345bool endsWith(const string & s, const char * suffix, size_t suffixsize) {
    289346    return endsWith( *s.inner, suffix, suffixsize );
    290347}
     
    316373
    317374
    318 int exclude(const string &s, const charclass &mask) {
     375int exclude(const string & s, const charclass & mask) {
    319376    return exclude( *s.inner, *mask.inner );
    320377}
    321378/*
    322 StrSlice exclude(string &s, const charclass &mask) {
     379StrSlice exclude(string & s, const charclass & mask) {
    323380}
    324381*/
    325382
    326 int include(const string &s, const charclass &mask) {
     383int include(const string & s, const charclass & mask) {
    327384    return include( *s.inner, *mask.inner );
    328385}
    329386
    330387/*
    331 StrSlice include(string &s, const charclass &mask) {
     388StrSlice include(string & s, const charclass & mask) {
    332389}
    333390*/
  • libcfa/src/collections/string_res.cfa

    r92355883 r2a301ff  
    99// Author           : Michael L. Brooks
    1010// Created On       : Fri Sep 03 11:00:00 2021
    11 // Last Modified By : Michael L. Brooks
    12 // Last Modified On : Fri Sep 03 11:00:00 2021
    13 // 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
    1414//
    1515
     
    1717#include "string_sharectx.hfa"
    1818#include "stdlib.hfa"
     19#include <ctype.h>
    1920
    2021// Workaround for observed performance penalty from calling CFA's alloc.
     
    134135        serr | nlOff;
    135136        serr | " lnth:" | lnth | " s:" | (void *)s | ",\"";
    136         for ( int i = 0; i < lnth; i += 1 ) {
     137        for ( i; lnth ) {
    137138            serr | s[i];
    138139        } // for
     
    198199// Output operator
    199200ofstream & ?|?(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;
    209203    return out;
    210204}
    211205
    212206void ?|?(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
     211ifstream & ?|?(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
    226249
    227250// Empty constructor
     
    338361    // adjust all substring string and handle locations, and check if any substring strings are outside the new base string
    339362    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 ) {
    341364        verify (p->Handle.s >= beforeBegin);
    342365        if ( p->Handle.s >= afterBegin ) {
     
    391414}
    392415
    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
     417static void locateInShareEditSet( string_res &this, string_res *&shareEditSetStartPeer, string_res *&shareEditSetEndPeer ) {
     418    shareEditSetStartPeer = & this;
     419    shareEditSetEndPeer = & this;
    398420    for (string_res * editPeer = this.shareEditSet_next; editPeer != &this; editPeer = editPeer->shareEditSet_next) {
    399421        if ( editPeer->Handle.s < shareEditSetStartPeer->Handle.s ) {
     
    404426        }
    405427    }
     428}
     429
     430static 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 );
    406435
    407436    verify( shareEditSetEndPeer->Handle.s >= shareEditSetStartPeer->Handle.s );
     
    589618
    590619bool contains(const string_res &s, char ch) {
    591     for (i; size(s)) {
     620    for ( i; size(s) ) {
    592621        if (s[i] == ch) return true;
    593622    }
     
    643672    }
    644673
    645     for (size_t i = fromPos; i < s.Handle.lnth; i++) {
     674    for ( i; fromPos ~ s.Handle.lnth ) {
    646675        size_t remaining = s.Handle.lnth - i;
    647676        // Never going to find the search string if the remaining string is
     
    652681
    653682        bool matched = true;
    654         for (size_t j = 0; j < searchsize; j++) {
     683        for ( j; searchsize ) {
    655684            if (search[j] != s.Handle.s[i + j]) {
    656685                matched = false;
     
    740769
    741770int exclude(const string_res &s, const charclass_res &mask) {
    742     for (int i = 0; i < size(s); i++) {
     771    for ( i; size(s) ) {
    743772        if ( test(mask, s[i]) ) return i;
    744773    }
     
    747776
    748777int include(const string_res &s, const charclass_res &mask) {
    749     for (int i = 0; i < size(s); i++) {
     778    for ( i; size(s) ) {
    750779        if ( ! test(mask, s[i]) ) return i;
    751780    }
     
    775804                for ( HandleNode *ni = HeaderPtr->flink; ni != HeaderPtr; ni = ni->flink ) {
    776805                        serr | "\tnode:" | ni | " lnth:" | ni->lnth | " s:" | (void *)ni->s | ",\"";
    777                         for ( int i = 0; i < ni->lnth; i += 1 ) {
     806                        for ( i; ni->lnth ) {
    778807                                serr | ni->s[i];
    779808                        } // for
     
    881910        for ( HandleNode *n = HeaderPtr->flink; n != HeaderPtr; n = n->flink ) {
    882911            serr | "\tnode:" | n | " lnth:" | n->lnth | " s:" | (void *)n->s | ",\"";
    883             for ( int i = 0; i < n->lnth; i += 1 ) {
    884                 serr | n->s[i];
     912            for ( i; n->lnth ) {
     913                        serr | n->s[i];
    885914            } // for
    886915            serr | "\" flink:" | n->flink | " blink:" | n->blink | nl;
     
    960989    EndVbyte = StartVbyte;
    961990    h = Header.flink;                                   // ignore header node
    962     for (;;) {
     991    for () {
    963992                memmove( EndVbyte, h->s, h->lnth );
    964993                obase = h->s;
     
    9711000                // check if any substrings are allocated within a string
    9721001               
    973                 for (;;) {
     1002                for () {
    9741003                        if ( h == &Header ) break;                      // end of header list ?
    9751004                        if ( h->s >= limit ) break;                     // outside of current string ?
     
    10011030                        serr | nlOff;
    10021031                        serr | "\tnode:" | n | " lnth:" | n->lnth | " s:" | (void *)n->s | ",\"";
    1003                         for ( int i = 0; i < n->lnth; i += 1 ) {
     1032                        for ( i; n->lnth ) {
    10041033                                serr | n->s[i];
    10051034                        } // for
     
    10361065                        serr | nlOff;
    10371066                        serr | "\tnode:" | n | " lnth:" | n->lnth | " s:" | (void *)n->s | ",\"";
    1038                         for ( int i = 0; i < n->lnth; i += 1 ) {
     1067                        for ( i; n->lnth ) {
    10391068                                serr | n->s[i];
    10401069                        } // for
  • libcfa/src/collections/string_res.hfa

    r92355883 r2a301ff  
    99// Author           : Michael L. Brooks
    1010// Created On       : Fri Sep 03 11:00:00 2021
    11 // Last Modified By : Michael L. Brooks
    12 // Last Modified On : Fri Sep 03 11:00:00 2021
    13 // Update Count     : 1
     11// Last Modified By : Peter A. Buhr
     12// Last Modified On : Sat Aug 12 15:45:47 2023
     13// Update Count     : 2
    1414//
    1515
     
    3030    VbyteHeap *ulink;                   // upward link
    3131
    32     char *s;                                            // pointer to byte string
     32    char *s;                                                    // pointer to byte string
    3333    unsigned int lnth;                                  // length of byte string
    3434}; // HandleNode
     
    101101ofstream & ?|?(ofstream &out, const string_res &s);
    102102void ?|?(ofstream &out, const string_res &s);
     103ifstream & ?|?(ifstream &in, string_res &s);
    103104
    104105// Concatenation
  • libcfa/src/collections/vector.cfa

    r92355883 r2a301ff  
    1010// Created On       : Tue Jul  5 18:07:52 2016
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Tue Jul  5 18:08:31 2016
    13 // Update Count     : 2
     12// Last Modified On : Wed Aug 30 21:27:31 2023
     13// Update Count     : 3
    1414//
    1515
    16 #include <containers/vector.hfa>
     16#include <collections/vector.hfa>
    1717
    1818#include <stdlib.hfa>
  • libcfa/src/common.hfa

    r92355883 r2a301ff  
    1010// Created On       : Wed Jul 11 17:54:36 2018
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Sat Oct  8 08:32:57 2022
    13 // Update Count     : 23
     12// Last Modified On : Mon Aug 14 17:01:47 2023
     13// Update Count     : 38
    1414//
    1515
     
    6666
    6767static 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; }
    6988        int min( int v1, int v2 ) { return v1 < v2 ? v1 : v2; }
    7089        unsigned int min( unsigned int v1, unsigned int v2 ) { return v1 < v2 ? v1 : v2; }
     
    7392        long long int min( long long int v1, long long int v2 ) { return v1 < v2 ? v1 : v2; }
    7493        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 ); } )                                      // generic
    76         T min( T v1, T v2 ) { return v1 < v2 ? v1 : v2; }
    7794
    78         char max( char v1, char v2 ) { return v1 > v2 ? v1 : v2; } // optimization
     95        char max( char v1, char v2 ) { return v1 > v2 ? v1 : v2; }
    7996        int max( int v1, int v2 ) { return v1 > v2 ? v1 : v2; }
    8097        unsigned int max( unsigned int v1, unsigned int v2 ) { return v1 > v2 ? v1 : v2; }
     
    83100        long long int max( long long int v1, long long int v2 ) { return v1 > v2 ? v1 : v2; }
    84101        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 ); } )                                      // generic
    86         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; }
    93102} // distribution
    94103
  • libcfa/src/concurrency/actor.hfa

    r92355883 r2a301ff  
    3939// #define ACTOR_STATS
    4040
     41// used to run and only track missed queue gulps
     42#ifdef ACTOR_STATS
     43#define ACTOR_STATS_QUEUE_MISSED
     44#endif
     45
    4146// forward decls
    4247struct actor;
     
    4853typedef allocation (*__receive_fn)(actor &, message &, actor **, message **);
    4954struct request {
    50     actor * receiver;
    51     message * msg;
    52     __receive_fn fn;
     55        actor * receiver;
     56        message * msg;
     57        __receive_fn fn;
    5358};
    5459
    5560struct a_msg {
    56     int m;
     61        int m;
    5762};
    5863static inline void ?{}( request & this ) {}
    5964static 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;
    6368}
    6469static 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;
    6873}
    6974
     
    7176// assumes gulping behaviour (once a remove occurs, removes happen until empty beforw next insert)
    7277struct 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;
    7580};
    7681static inline void ?{}( copy_queue & this ) {}
    7782static 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;
    8489}
    8590static 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);
    8893}
    8994
    9095static inline void insert( copy_queue & this, request & elem ) with(this) {
    91     if ( count >= buffer_size ) { // increase arr size
    92         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++;
    99104}
    100105
     
    102107// it is not supported to call insert() before the array is fully empty
    103108static 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;
    112117}
    113118
    114119// try to reclaim some memory if less than half of buffer is utilized
    115120static 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 memory
     121        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
    120125}
    121126
     
    123128
    124129struct 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;
    132136    #endif
     137    #ifdef ACTOR_STATS_QUEUE_MISSED
     138        size_t missed;                                                                          // transfers skipped due to being_processed flag being up
     139        #endif
    133140}; // work_queue
    134141static inline void ?{}( work_queue & this, size_t buf_size, unsigned int i ) with(this) {
    135     owned_queue = alloc();      // allocated separately to avoid false sharing
    136     (*owned_queue){ buf_size };
    137     c_queue = owned_queue;
    138     being_processed = false;
    139     #ifdef ACTOR_STATS
    140     id = i;
    141     missed = 0;
    142     #endif
     142        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
    143150}
    144151
     
    147154
    148155static 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 );
    152159} // insert
    153160
    154161static inline void transfer( work_queue & this, copy_queue ** transfer_to ) with(this) {
    155     lock( mutex_lock __cfaabi_dbg_ctx2 );
    156     #ifdef __STEAL
    157 
    158     // check if queue is being processed elsewhere
    159     if ( unlikely( being_processed ) ) {
    160         #ifdef ACTOR_STATS
    161         missed++;
    162         #endif
    163         unlock( mutex_lock );
    164         return;
    165     }
    166 
    167     being_processed = c_queue->count != 0;
    168     #endif // __STEAL
    169 
    170     c_queue->utilized = c_queue->count;
    171 
    172     // swap copy queue ptrs
    173     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 );
    177184} // transfer
    178185
    179186// needed since some info needs to persist past worker lifetimes
    180187struct worker_info {
    181     volatile unsigned long long stamp;
    182     #ifdef ACTOR_STATS
    183     size_t stolen_from, try_steal, stolen, empty_stolen, failed_swaps, msgs_stolen;
    184     unsigned long long processed;
    185     size_t gulps;
    186     #endif
     188        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
    187194};
    188195static inline void ?{}( worker_info & this ) {
    189     #ifdef ACTOR_STATS
    190     this.stolen_from = 0;
    191     this.try_steal = 0;                             // attempts to steal
    192     this.stolen = 0;                                // successful steals
    193     this.processed = 0;                             // requests processed
    194     this.gulps = 0;                                 // number of gulps
    195     this.failed_swaps = 0;                          // steal swap failures
    196     this.empty_stolen = 0;                          // queues empty after steal
    197     this.msgs_stolen = 0;                           // number of messages stolen
    198     #endif
    199     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();
    200207}
    201208
     
    205212// #endif
    206213thread 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;
    212219};
    213220
     
    215222// aggregate counters for statistics
    216223size_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;
    218225#endif
    219226static 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 queues
    223     this.current_queue = current_queue;             // currently gulped queue (start with empty queue to use in swap later)
    224     this.executor_ = executor_;                     // pointer to current executor
    225     this.start = start;                             // start of worker's subrange of request_queues
    226     this.range = range;                             // size of worker's subrange of request_queues
    227     this.id = id;                                   // worker's id and index in array of workers
     227        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
    228235}
    229236
    230237static bool no_steal = false;
    231238struct executor {
    232     cluster * cluster;                                                      // if workers execute on separate cluster
    233         processor ** processors;                                            // array of virtual processors adding parallelism for workers
    234         work_queue * request_queues;                                // master array of work request queues
    235     copy_queue * local_queues;                      // array of all worker local queues to avoid deletion race
    236         work_queue ** worker_req_queues;                // secondary array of work queues to allow for swapping
    237     worker ** workers;                                                          // array of workers executing work requests
    238     worker_info * w_infos;                          // array of info about each worker
    239         unsigned int nprocessors, nworkers, nrqueues;   // number of processors/threads/request queues
    240         bool seperate_clus;                                                             // use same or separate cluster for executor
    241     volatile bool is_shutdown;                      // flag to communicate shutdown to worker threads
     239        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
    242249}; // executor
    243250
     
    246253// #endif
    247254static inline void ^?{}( worker & mutex this ) with(this) {
    248     #ifdef ACTOR_STATS
    249     __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     #endif
     255        #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
    274281}
    275282
    276283static 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_STATS
    288     // stolen_arr = aalloc( nrqueues );
    289     // replaced_queue = aalloc( nrqueues );
    290     __total_workers = nworkers;
    291     #endif
    292 
    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     } // for
     284        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
    323330}
    324331static 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__ }; }
     
    329336
    330337static 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);
    347378    #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 stats
    358     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);
    366379    #endif
    367        
     380               
    368381}
    369382
     
    372385
    373386static 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 actors
    378     if ( unlikely( temp == MAX ) ) temp = __atomic_fetch_add( &__next_ticket, 1, __ATOMIC_SEQ_CST) % nrqueues;
    379     return temp;
    380     #else
    381     return __atomic_fetch_add( &__next_ticket, 1, __ATOMIC_RELAXED) % nrqueues;
    382     #endif
     387        #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
    383396} // tickets
    384397
    385398// TODO: update globals in this file to be static fields once the static fields project is done
    386399static executor * __actor_executor_ = 0p;
    387 static bool __actor_executor_passed = false;            // was an executor passed to start_actor_system
    388 static size_t __num_actors_ = 0;                                        // number of actor objects in system
     400static bool __actor_executor_passed = false;                    // was an executor passed to start_actor_system
     401static size_t __num_actors_ = 0;                                                // number of actor objects in system
    389402static struct thread$ * __actor_executor_thd = 0p;              // used to wake executor after actors finish
    390403struct actor {
    391     size_t ticket;                                          // executor-queue handle
    392     allocation allocation_;                                         // allocation action
    393     inline virtual_dtor;
     404        size_t ticket;                                                                          // executor-queue handle
     405        allocation alloc;                                                                       // allocation action
     406        inline virtual_dtor;
    394407};
    395408
    396409static 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 receive
    398     // member must be called to end it
    399     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_STATS
    404     __atomic_fetch_add( &__num_actors_stats, 1, __ATOMIC_SEQ_CST );
    405     #endif
     410        // 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
    406419}
    407420
    408421static 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 terminated
    414                 ^?{}(this);
    415                 break;
    416             case Finished:
    417                 CFA_DEBUG( this.ticket = MAX; );        // mark as terminated
    418                 break;
    419             default: ;                                                          // stop warning
    420         }
    421 
    422         if ( unlikely( __atomic_add_fetch( &__num_actors_, -1, __ATOMIC_RELAXED ) == 0 ) ) { // all actors have terminated
    423             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        }
    426439}
    427440
    428441struct message {
    429     allocation allocation_;                     // allocation action
    430     inline virtual_dtor;
     442        allocation alloc;                                                                       // allocation action
     443        inline virtual_dtor;
    431444};
    432445
    433446static inline void ?{}( message & this ) {
    434     this.allocation_ = Nodelete;
     447        this.alloc = Nodelete;
    435448}
    436449static inline void ?{}( message & this, allocation alloc ) {
    437     memcpy( &this.allocation_, &alloc, sizeof(allocation) ); // optimization to elide ctor
    438     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; );
    439452}
    440453static 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        )
    442460}
    443461
    444462static 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}
     470static 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}
     476static inline allocation get_allocation( message & this ) {
     477        return this.alloc;
    454478}
    455479
    456480static 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 );
    464488}
    465489
     
    467491// returns ptr to newly owned queue if swap succeeds
    468492static 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 stolen
    473     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 false
    476     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 false
    480     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 val
    483         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 atomically
    487     request_queues[my_idx] = other_queue; // last write does not need to be atomic
    488     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;
    489513}
    490514
    491515// once a worker to steal from has been chosen, choose queue to steal from
    492516static 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 shutdown
    494     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 on
    513         if ( curr_steal_queue == 0p || curr_steal_queue->being_processed || is_empty( *curr_steal_queue->c_queue ) )
    514             continue;
    515 
    516         #ifdef ACTOR_STATS
    517         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         #else
    529         curr_steal_queue = try_swap_queues( this, i + vic_start, swap_idx );
    530         #endif // ACTOR_STATS
    531 
    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;
    536560}
    537561
    538562// choose a worker to steal from
    539563static inline void steal_work( worker & this, unsigned int swap_idx ) with(this) {
    540     #if RAND
    541     unsigned int victim = prng( executor_->nworkers );
    542     if ( victim == id ) victim = ( victim + 1 ) % executor_->nworkers;
    543     choose_queue( this, victim, swap_idx );
    544     #elif SEARCH
    545     unsigned long long min = MAX; // smaller timestamp means longer since service
    546     int min_id = 0; // use ints not uints to avoid integer underflow without hacky math
    547     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     #endif
     564        #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
    559583}
    560584
    561585#define CHECK_TERMINATION if ( unlikely( executor_->is_shutdown ) ) break Exit
    562586void 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, &current_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;
    625608        #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, &current_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
    632660}
    633661
    634662static 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);
    636664}
    637665
    638666static 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 );
    641669}
    642670
    643671static inline void __reset_stats() {
    644     #ifdef ACTOR_STATS
    645     __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     #endif
     672        #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
    654682}
    655683
    656684static 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 };
    661689}
    662690
     
    664692
    665693static 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;
    670698}
    671699
    672700static inline void stop_actor_system() {
    673     park( ); // will be unparked when actor system is finished
    674 
    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;
    680708}
    681709
    682710// Default messages to send to any actor to change status
    683711// 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 
     712message __base_msg_finished @= { .alloc : Finished };
     713struct delete_msg_t { inline message; } delete_msg = __base_msg_finished;
     714struct destroy_msg_t { inline message; } destroy_msg = __base_msg_finished;
     715struct finished_msg_t { inline message; } finished_msg = __base_msg_finished;
     716
     717allocation receive( actor & this, delete_msg_t & msg ) { return Delete; }
     718allocation receive( actor & this, destroy_msg_t & msg ) { return Destroy; }
     719allocation receive( actor & this, finished_msg_t & msg ) { return Finished; }
  • libcfa/src/concurrency/alarm.hfa

    r92355883 r2a301ff  
    1010// Created On       : Fri Jun 2 11:31:25 2017
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Mon Mar 26 16:25:41 2018
    13 // Update Count     : 11
     12// Last Modified On : Wed Aug 30 21:27:40 2023
     13// Update Count     : 12
    1414//
    1515
     
    2323#include "time.hfa"
    2424
    25 #include "containers/list.hfa"
     25#include "collections/list.hfa"
    2626
    2727struct thread$;
  • libcfa/src/concurrency/channel.hfa

    r92355883 r2a301ff  
    6868    #endif
    6969};
     70static inline void ?{}( channel(T) & this, channel(T) this2 ) = void;
     71static inline void ?=?( channel(T) & this, channel(T) this2 ) = void;
    7072
    7173static inline void ?{}( channel(T) &c, size_t _size ) with(c) {
     
    326328    return retval;
    327329}
     330static 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
     337static inline void ?<<?( channel(T) & chan, T elem ) { insert( chan, elem ); }
     338static inline void ?<<?( T & ret, channel(T) & chan ) { ret = remove( chan ); }
    328339
    329340///////////////////////////////////////////////////////////////////////////////////////////
     
    340351    unlock( mutex_lock );
    341352
    342     // only return true when not special OR case, not exceptional calse and status is SAT
    343     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;
    344355}
    345356
     
    363374// type used by select statement to capture a chan read as the selected operation
    364375struct chan_read {
    365     T & ret;
    366     channel(T) & chan;
     376    T * ret;
     377    channel(T) * chan;
    367378};
    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
     381static inline void ?{}( chan_read(T) & cr, channel(T) * chan, T * ret ) {
     382    cr.chan = chan;
     383    cr.ret = ret;
     384}
     385static inline chan_read(T) ?<<?( T & ret, channel(T) & chan ) { chan_read(T) cr{ &chan, &ret }; return cr; }
     386
     387static inline void __handle_select_closed_read( chan_read(T) & this, select_node & node ) with(*this.chan, this) {
     388    __closed_remove( *chan, *ret );
    377389    // if we get here then the insert succeeded
    378390    __make_select_node_available( node );
    379391}
    380392
    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 close
     393static 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
    384396
    385397    #ifdef CHAN_STATS
     
    396408
    397409            if ( __handle_pending( prods, node ) ) {
    398                 __prods_handoff( chan, ret );
     410                __prods_handoff( *chan, *ret );
    399411                __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
    400412                unlock( mutex_lock );
     
    422434    ZeroSize: if ( size == 0 && !prods`isEmpty ) {
    423435        if ( !__handle_waituntil_OR( prods ) ) break ZeroSize;
    424         __prods_handoff( chan, ret );
     436        __prods_handoff( *chan, *ret );
    425437        __set_avail_then_unlock( node, mutex_lock );
    426438        return true;
     
    439451
    440452    // Remove from buffer
    441     __do_remove( chan, ret );
     453    __do_remove( *chan, *ret );
    442454    __set_avail_then_unlock( node, mutex_lock );
    443455    return true;
    444456}
    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 );
     457static inline bool unregister_select( chan_read(T) & this, select_node & node ) { return unregister_chan( *this.chan, node ); }
     458static 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    }
    449463    // 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
     468struct 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
     474static inline void ?{}( chan_read_no_ret(T) & this, channel(T) & chan ) {
     475    this.c_read{ &chan, &this.retval };
     476}
     477
     478static inline chan_read_no_ret(T) remove( channel(T) & chan ) { chan_read_no_ret(T) c_read{ chan }; return c_read; }
     479static 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}
     483static inline bool unregister_select( chan_read_no_ret(T) & this, select_node & node ) { return unregister_select( this.c_read, node ); }
     484static inline bool on_selected( chan_read_no_ret(T) & this, select_node & node ) { return on_selected( this.c_read, node ); }
    451485
    452486// type used by select statement to capture a chan write as the selected operation
    453487struct chan_write {
    454488    T elem;
    455     channel(T) & chan;
     489    channel(T) * chan;
    456490};
    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
     493static inline void ?{}( chan_write(T) & cw, channel(T) * chan, T elem ) {
     494    cw.chan = chan;
    460495    memcpy( (void *)&cw.elem, (void *)&elem, sizeof(T) );
    461496}
    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 );
     497static inline chan_write(T) ?<<?( channel(T) & chan, T elem ) { chan_write(T) cw{ &chan, elem }; return cw; }
     498static inline chan_write(T) insert( T elem, channel(T) & chan) { chan_write(T) cw{ &chan, elem }; return cw; }
     499
     500static inline void __handle_select_closed_write( chan_write(T) & this, select_node & node ) with(*this.chan, this) {
     501    __closed_insert( *chan, elem );
    466502    // if we get here then the insert succeeded
    467503    __make_select_node_available( node );
    468504}
    469505
    470 static inline bool register_select( chan_write(T) & this, select_node & node ) with(this.chan, this) {
     506static inline bool register_select( chan_write(T) & this, select_node & node ) with(*this.chan, this) {
    471507    lock( mutex_lock );
    472508    node.extra = &elem; // set .extra so that if it == 0p later in on_selected it is due to channel close
     
    486522
    487523            if ( __handle_pending( cons, node ) ) {
    488                 __cons_handoff( chan, elem );
     524                __cons_handoff( *chan, elem );
    489525                __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
    490526                unlock( mutex_lock );
     
    513549    ConsEmpty: if ( !cons`isEmpty ) {
    514550        if ( !__handle_waituntil_OR( cons ) ) break ConsEmpty;
    515         __cons_handoff( chan, elem );
     551        __cons_handoff( *chan, elem );
    516552        __set_avail_then_unlock( node, mutex_lock );
    517553        return true;
     
    530566
    531567    // otherwise carry out write either via normal insert
    532     __buf_insert( chan, elem );
     568    __buf_insert( *chan, elem );
    533569    __set_avail_then_unlock( node, mutex_lock );
    534570    return true;
    535571}
    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 
     572static inline bool unregister_select( chan_write(T) & this, select_node & node ) { return unregister_chan( *this.chan, node ); }
     573
     574static 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    }
    542579    // This is only reachable if not closed or closed exception was handled
     580    return true;
    543581}
    544582
  • libcfa/src/concurrency/coroutine.cfa

    r92355883 r2a301ff  
    2828#include "kernel/private.hfa"
    2929#include "exception.hfa"
     30#include "exception.h"
    3031#include "math.hfa"
    3132
     
    7778        free( desc->cancellation );
    7879        desc->cancellation = 0p;
     80}
     81
     82// helper for popping from coroutine's ehm buffer
     83inline 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;
    7988}
    8089
     
    121130        last = 0p;
    122131        cancellation = 0p;
     132    ehm_state.ehm_buffer{};
     133    ehm_state.buffer_lock{};
     134    ehm_state.ehm_enabled = false;
    123135}
    124136
    125137void ^?{}(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
    126155        if(this.state != Halted && this.state != Start && this.state != Primed) {
    127156                coroutine$ * src = active_coroutine();
     
    283312}
    284313
     314
     315////////////////////////////////////////////////////////////////////////////////////////////////////
     316// non local ehm routines
     317
     318void defaultResumeAtHandler( exception_t * except ) {
     319    __cfaehm_allocate_exception( except );
     320    free( except );
     321    __cfaehm_begin_unwind( (void(*)(exception_t *))defaultTerminationHandler );
     322}
     323
     324bool 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
     344bool poll() libcfa_public { return poll( active_coroutine() ); }
     345coroutine$ * resumer() libcfa_public { return active_coroutine()->last; }
     346
     347// user facing ehm operations
     348forall(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)
     363forall(exceptT *, T & | ehm_resume_at( exceptT, T ))
     364void 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
     375forall(exceptT * | { void $throwResume(exceptT &); })
     376void 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
    285386// Local Variables: //
    286387// mode: c //
  • libcfa/src/concurrency/coroutine.hfa

    r92355883 r2a301ff  
    1919#include "invoke.h"
    2020#include "../exception.hfa"
     21
     22//-----------------------------------------------------------------------------
     23// Type used to store and queue nonlocal exceptions on coroutines
     24struct nonlocal_exception {
     25    exception_t * the_exception;
     26    nonlocal_exception * next;
     27};
     28static inline void ?{} ( nonlocal_exception & this, exception_t * ex ) with(this) {
     29    the_exception = ex;
     30    next = 0p;
     31}
     32
     33static inline nonlocal_exception *& get_next( nonlocal_exception & this ) __attribute__((const)) {
     34    return this.next;
     35}
    2136
    2237//-----------------------------------------------------------------------------
     
    203218}
    204219
     220// non local ehm and coroutine utility routines
     221bool poll( coroutine$ * cor );
     222bool poll();
     223coroutine$ * resumer();
     224
     225forall(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
     234forall(exceptT *, T & | is_coroutine(T))
     235trait ehm_resume_at { void $throwResume(exceptT &); };
     236
     237// general resumeAt
     238forall(exceptT *, T & | ehm_resume_at( exceptT, T ))
     239void resumeAt( T & receiver, exceptT & ex );
     240
     241// resumeAt for underlying coroutine$ type
     242forall(exceptT * | { void $throwResume(exceptT &); })
     243void resumeAt( coroutine$ * receiver, exceptT & ex );
     244
    205245// Local Variables: //
    206246// mode: c //
  • libcfa/src/concurrency/future.hfa

    r92355883 r2a301ff  
    3939        futex_mutex lock;
    4040        };
     41    __CFA_SELECT_GET_TYPE( future(T) );
    4142
    4243    struct future_node {
     
    180181        }
    181182               
    182         void on_selected( future(T) & this, select_node & node ) {}
     183        bool on_selected( future(T) & this, select_node & node ) { return true; }
    183184        }
    184185}
  • libcfa/src/concurrency/invoke.h

    r92355883 r2a301ff  
    1010// Created On       : Tue Jan 17 12:27:26 2016
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Tue Mar 14 13:39:31 2023
    13 // Update Count     : 59
     12// Last Modified On : Wed Aug 30 21:27:51 2023
     13// Update Count     : 60
    1414//
    1515
    1616// No not use #pragma once was this file is included twice in some places. It has its own guard system.
    1717
    18 #include "bits/containers.hfa"
     18#include "bits/collections.hfa"
    1919#include "bits/defs.hfa"
    2020#include "bits/locks.hfa"
     
    2323
    2424#ifdef __cforall
    25 #include "containers/list.hfa"
     25#include "collections/list.hfa"
    2626extern "C" {
    2727#endif
     
    7474        };
    7575
     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
    7687        enum __Coroutine_State { Halted, Start, Primed, Blocked, Ready, Active, Cancelled, Halting };
    7788
     
    98109                struct _Unwind_Exception * cancellation;
    99110
     111        // Non-local exception handling information
     112        struct nonlocal_ehm ehm_state;
    100113        };
    101114        // Wrapper for gdb
     
    242255        #ifdef __cforall
    243256        extern "Cforall" {
     257        static inline bool exception_in_flight() {
     258            return __get_stack( &active_thread()->self_cor )->exception_context.current_exception != 0p;
     259        }
     260
    244261                static inline thread$ * volatile & ?`next ( thread$ * this ) {
    245262                        return this->user_link.next;
  • libcfa/src/concurrency/iofwd.hfa

    r92355883 r2a301ff  
    1010// Created On       : Thu Apr 23 17:31:00 2020
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Mon Mar 13 23:54:57 2023
    13 // Update Count     : 1
     12// Last Modified On : Fri Jul 21 21:36:01 2023
     13// Update Count     : 3
    1414//
    1515
     
    1818#include <unistd.h>
    1919#include <sys/socket.h>
     20#include <string.h>                                                                             // memset
    2021
    2122extern "C" {
     
    151152#if CFA_HAVE_LINUX_IO_URING_H
    152153        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 ) );
    167155        }
    168156#endif
  • libcfa/src/concurrency/kernel.cfa

    r92355883 r2a301ff  
    569569                returnToKernel();
    570570        __enable_interrupts_checked();
    571 
    572571}
    573572
  • libcfa/src/concurrency/kernel.hfa

    r92355883 r2a301ff  
    1010// Created On       : Tue Jan 17 12:27:26 2017
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Tue Feb  4 12:29:26 2020
    13 // Update Count     : 22
     12// Last Modified On : Wed Aug 30 21:28:46 2023
     13// Update Count     : 23
    1414//
    1515
     
    2020#include "coroutine.hfa"
    2121
    22 #include "containers/list.hfa"
     22#include "collections/list.hfa"
    2323
    2424extern "C" {
  • libcfa/src/concurrency/kernel/startup.cfa

    r92355883 r2a301ff  
    487487        last = 0p;
    488488        cancellation = 0p;
     489    ehm_state.ehm_buffer{};
     490    ehm_state.buffer_lock{};
     491    ehm_state.ehm_enabled = false;
    489492}
    490493
  • libcfa/src/concurrency/locks.cfa

    r92355883 r2a301ff  
    239239}
    240240
    241 void on_selected( blocking_lock & this, select_node & node ) {}
     241bool on_selected( blocking_lock & this, select_node & node ) { return true; }
    242242
    243243//-----------------------------------------------------------------------------
  • libcfa/src/concurrency/locks.hfa

    r92355883 r2a301ff  
    2121
    2222#include "bits/weakso_locks.hfa"
    23 #include "containers/lockfree.hfa"
    24 #include "containers/list.hfa"
     23#include "collections/lockfree.hfa"
     24#include "collections/list.hfa"
    2525
    2626#include "limits.hfa"
     
    112112static inline bool   register_select( single_acquisition_lock & this, select_node & node ) { return register_select( (blocking_lock &)this, node ); }
    113113static 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 ); }
     114static 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 );
    115116
    116117//----------
     
    129130static inline bool   register_select( owner_lock & this, select_node & node ) { return register_select( (blocking_lock &)this, node ); }
    130131static 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 ); }
     132static inline bool   on_selected( owner_lock & this, select_node & node ) { return on_selected( (blocking_lock &)this, node ); }
     133__CFA_SELECT_GET_TYPE( owner_lock );
    132134
    133135//-----------------------------------------------------------------------------
     
    138140};
    139141
    140 static inline void ?{}(mcs_node & this) { this.next = 0p; }
     142static inline void ?{}( mcs_node & this ) { this.next = 0p; }
    141143
    142144static inline mcs_node * volatile & ?`next ( mcs_node * node ) {
     
    148150};
    149151
    150 static inline void lock(mcs_lock & l, mcs_node & n) {
     152static inline void lock( mcs_lock & l, mcs_node & n ) {
    151153        if(push(l.queue, &n))
    152154                wait(n.sem);
     
    172174};
    173175
    174 static inline void ?{}(mcs_spin_node & this) { this.next = 0p; this.locked = true; }
     176static inline void ?{}( mcs_spin_node & this ) { this.next = 0p; this.locked = true; }
    175177
    176178struct mcs_spin_lock {
     
    178180};
    179181
    180 static inline void lock(mcs_spin_lock & l, mcs_spin_node & n) {
     182static inline void lock( mcs_spin_lock & l, mcs_spin_node & n ) {
    181183    n.locked = true;
    182184        mcs_spin_node * prev = __atomic_exchange_n(&l.queue.tail, &n, __ATOMIC_SEQ_CST);
     
    271273};
    272274static 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;
     275static inline void ?{}( go_mutex & this, go_mutex this2 ) = void;
     276static inline void ?=?( go_mutex & this, go_mutex this2 ) = void;
    275277
    276278static inline bool internal_try_lock(go_mutex & this, int & compare_val, int new_val ) with(this) {
     
    619621}
    620622
    621 static inline void on_selected( simple_owner_lock & this, select_node & node ) {}
    622 
     623static inline bool on_selected( simple_owner_lock & this, select_node & node ) { return true; }
     624__CFA_SELECT_GET_TYPE( simple_owner_lock );
    623625
    624626//-----------------------------------------------------------------------------
  • libcfa/src/concurrency/once.hfa

    r92355883 r2a301ff  
    1616#pragma once
    1717
    18 #include "containers/lockfree.hfa"
     18#include "collections/lockfree.hfa"
    1919#include "kernel/fwd.hfa"
    2020
  • libcfa/src/concurrency/select.cfa

    r92355883 r2a301ff  
    4949    return false;
    5050}
    51 void on_selected( select_timeout_node & this, select_node & node ) {}
     51bool on_selected( select_timeout_node & this, select_node & node ) { return true; }
    5252
    5353// Gateway routine to wait on duration
  • libcfa/src/concurrency/select.hfa

    r92355883 r2a301ff  
    1717#pragma once
    1818
    19 #include "containers/list.hfa"
     19#include "collections/list.hfa"
    2020#include "alarm.hfa"
    2121#include "kernel.hfa"
     
    9494
    9595    // 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 & );
    9998};
     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
    100103
    101104//=============================================================================================
     
    208211bool register_select( select_timeout_node & this, select_node & node );
    209212bool unregister_select( select_timeout_node & this, select_node & node );
    210 void on_selected( select_timeout_node & this, select_node & node );
     213bool on_selected( select_timeout_node & this, select_node & node );
     214select_timeout_node __CFA_select_get_type( select_timeout_node this );
    211215
    212216// Gateway routines to waituntil on duration
    213217select_timeout_node timeout( Duration duration );
    214218select_timeout_node sleep( Duration duration );
     219
  • libcfa/src/concurrency/stats.cfa

    r92355883 r2a301ff  
    1111#if !defined(__CFA_NO_STATISTICS__)
    1212        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 ) );
    3914
    4015                #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 ) );
    6817                #endif
    6918
  • libcfa/src/exception.c

    r92355883 r2a301ff  
    99// Author           : Andrew Beach
    1010// Created On       : Mon Jun 26 15:13:00 2017
    11 // Last Modified By : Andrew Beach
    12 // Last Modified On : Wed Feb 24 13:40:00 2021
    13 // Update Count     : 36
     11// Last Modified By : Peter A. Buhr
     12// Last Modified On : Thu Aug 10 16:45:22 2023
     13// Update Count     : 69
    1414//
    1515
     
    2727#include "stdhdr/assert.h"
    2828#include "virtual.h"
     29
     30extern void __cabi_abort( const char fmt[], ... );
    2931
    3032#pragma GCC visibility push(default)
     
    123125
    124126// Creates a copy of the indicated exception and sets current_exception to it.
    125 static void __cfaehm_allocate_exception( exception_t * except ) {
     127void __cfaehm_allocate_exception( exception_t * except ) {
    126128        struct exception_context_t * context = this_exception_context();
    127129
     
    192194
    193195        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                );
    195203        } else {
    196204                return _URC_NO_REASON;
     
    209217        struct exception_context_t * context = this_exception_context();
    210218        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         }
    220219
    221220        _Unwind_Reason_Code ret;
     
    239238
    240239// The exception that is being thrown must already be stored.
    241 static void __cfaehm_begin_unwind(void(*defaultHandler)(exception_t *)) {
     240void __cfaehm_begin_unwind(void(*defaultHandler)(exception_t *)) {
    242241        struct exception_context_t * context = this_exception_context();
    243242        if ( NULL == context->current_exception ) {
     
    568567        "       .hidden CFA.ref.__gcfa_personality_v0\n"
    569568        "       .weak   CFA.ref.__gcfa_personality_v0\n"
    570         // No clue what this does specifically
    571         "       .section        .data.rel.local.CFA.ref.__gcfa_personality_v0,\"awG\",@progbits,CFA.ref.__gcfa_personality_v0,comdat\n"
    572569#if defined( __x86_64 ) || defined( __i386 )
    573570        "       .align 8\n"
  • libcfa/src/exception.h

    r92355883 r2a301ff  
    5050void __cfaehm_rethrow_terminate() __attribute__((noreturn));
    5151void __cfaehm_throw_resume(exception_t * except, void (*)(exception_t *));
     52
     53// Used in non-local ehm (see coroutine.cfa)
     54void __cfaehm_allocate_exception( exception_t * except );
     55void __cfaehm_begin_unwind(void(*defaultHandler)(exception_t *));
     56
    5257
    5358// Function catches termination exceptions.
  • libcfa/src/executor.baseline.txt

    r92355883 r2a301ff  
    55
    66#include <thread.hfa>
    7 #include <containers/list.hfa>
     7#include <collections/list.hfa>
    88
    99forall( T & | $dlistable(T, T) ) {
  • libcfa/src/executor.cfa

    r92355883 r2a301ff  
    55
    66#include <thread.hfa>
    7 #include <containers/list.hfa>
     7#include <collections/list.hfa>
    88
    99forall( T &, TLink& = dlink(T) | embedded(T, TLink, dlink(T)) ) {
  • libcfa/src/fstream.cfa

    r92355883 r2a301ff  
    1010// Created On       : Wed May 27 17:56:53 2015
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Sat Jun 17 08:51:12 2023
    13 // Update Count     : 528
     12// Last Modified On : Fri Aug 18 10:41:17 2023
     13// Update Count     : 541
    1414//
    1515
     
    2424
    2525#pragma GCC visibility push(default)
     26
    2627
    2728// *********************************** ofstream ***********************************
     
    4344} // ?{}
    4445
     46inline bool getNL$( ofstream & os ) { return os.sawNL$; }
     47inline bool setNL$( ofstream & os, bool state ) { bool temp = os.sawNL$; os.sawNL$ = state; return temp; }
     48inline bool getANL$( ofstream & os ) { return os.nlOnOff$; }
     49inline bool setANL$( ofstream & os, bool state ) { bool temp = os.nlOnOff$; os.nlOnOff$ = state; return temp; }
     50
    4551inline bool sepPrt$( ofstream & os ) { setNL$( os, false ); return os.sepOnOff$; }
    4652inline void sepReset$( ofstream & os ) { os.sepOnOff$ = os.sepDefault$; }
     
    4854inline const char * sepGetCur$( ofstream & os ) { return os.sepCur$; }
    4955inline 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
    5357inline bool getPrt$( ofstream & os ) { return os.prt$; }
    54 inline void setPrt$( ofstream & os, bool state ) { os.prt$ = state; }
     58inline bool setPrt$( ofstream & os, bool state ) { bool temp = os.prt$; os.prt$ = state; return temp; }
    5559
    5660inline void lock( ofstream & os ) with( os ) { lock( os.lock$ ); }
     
    6367void ^?{}( ofstream & os ) { close( os ); }
    6468
    65 void sepOn( ofstream & os ) { os.sepOnOff$ = ! getNL$( os ); }
    66 void sepOff( ofstream & os ) { os.sepOnOff$ = false; }
    67 
    68 bool sepDisable( ofstream & os ) {
     69void nlOn( ofstream & os ) { os.nlOnOff$ = true; }
     70void nlOff( ofstream & os ) { os.nlOnOff$ = false; }
     71
     72void sep( ofstream & os ) { os.sepOnOff$ = ! getNL$( os ); }
     73void nosep( ofstream & os ) { os.sepOnOff$ = false; }
     74
     75bool 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
     82bool sepOff( ofstream & os ) {
    6983        bool temp = os.sepDefault$;
    7084        os.sepDefault$ = false;
    7185        sepReset$( os );
    7286        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
    8488
    8589const char * sepGet( ofstream & os ) { return os.separator$; }
     
    209213
    210214bool getANL$( ifstream & os ) { return os.nlOnOff$; }
     215bool setANL$( ifstream & os, bool state ) { bool temp = os.nlOnOff$; os.nlOnOff$ = state; return temp; }
    211216
    212217inline void lock( ifstream & os ) with( os ) { lock( os.lock$ ); }
  • libcfa/src/fstream.hfa

    r92355883 r2a301ff  
    1010// Created On       : Wed May 27 17:56:53 2015
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Mon Jun  5 22:00:20 2023
    13 // Update Count     : 246
     12// Last Modified On : Fri Aug 18 10:41:15 2023
     13// Update Count     : 258
    1414//
    1515
     
    3434        char separator$[ofstream_sepSize];
    3535        char tupleSeparator$[ofstream_sepSize];
    36         multiple_acquisition_lock lock$;
     36        multiple_acquisition_lock lock$;                                        // used by trait is_lock for mutex statement
    3737}; // ofstream
    3838
     
    4040
    4141// private
     42bool getNL$( ofstream & );
     43bool setNL$( ofstream &, bool );
     44bool getANL$( ofstream & );
     45bool setANL$( ofstream &, bool );
     46
    4247bool sepPrt$( ofstream & );
    4348void sepReset$( ofstream & );
     
    4550const char * sepGetCur$( ofstream & );
    4651void sepSetCur$( ofstream &, const char [] );
    47 bool getNL$( ofstream & );
    48 void setNL$( ofstream &, bool );
    49 bool getANL$( ofstream & );
     52
    5053bool getPrt$( ofstream & );
    51 void setPrt$( ofstream &, bool );
     54bool setPrt$( ofstream &, bool );
    5255
    5356void lock( ofstream & );
     
    5558
    5659// public
    57 void sepOn( ofstream & );
    58 void sepOff( ofstream & );
    59 bool sepDisable( ofstream & );
    60 bool sepEnable( ofstream & );
    6160void nlOn( ofstream & );
    6261void nlOff( ofstream & );
    6362
     63void sep( ofstream & );
     64void nosep( ofstream & );
     65bool sepOn( ofstream & );
     66bool sepOff( ofstream & );
    6467const char * sepGet( ofstream & );
    6568void sepSet( ofstream &, const char [] );
     
    99102        void * file$;
    100103        bool nlOnOff$;
    101         multiple_acquisition_lock lock$;
     104        multiple_acquisition_lock lock$;                                        // used by trait is_lock for mutex statement
    102105}; // ifstream
    103106
     
    106109// private
    107110bool getANL$( ifstream & );
     111bool setANL$( ifstream &, bool );
    108112
    109113void lock( ifstream & );
  • libcfa/src/gmp.hfa

    r92355883 r2a301ff  
    1010// Created On       : Tue Apr 19 08:43:43 2016
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Tue Apr 20 20:59:21 2021
    13 // Update Count     : 32
     12// Last Modified On : Tue Jul 18 11:04:54 2023
     13// Update Count     : 35
    1414//
    1515
     
    265265                        if ( sepPrt$( os ) ) fmt( os, "%s", sepGetCur$( os ) );
    266266                        gmp_printf( "%Zd", mp.mpz );
    267                         sepOn( os );
     267                        sep( os );
    268268                        return os;
    269269                } // ?|?
    270 
    271                 void ?|?( ostype & os, Int mp ) {
    272                         (ostype)(os | mp); ends( os );
    273                 } // ?|?
     270                OSTYPE_VOID_IMPL( Int )
    274271        } // distribution
    275272} // distribution
  • libcfa/src/heap.cfa

    r92355883 r2a301ff  
    1010// Created On       : Tue Dec 19 21:58:35 2017
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Fri Dec 30 08:37:37 2022
    13 // Update Count     : 1605
     12// Last Modified On : Wed Aug  2 18:48:30 2023
     13// Update Count     : 1614
    1414//
    1515
     
    369369static __thread size_t PAD1 CALIGN TLSMODEL __attribute__(( unused )); // protect false sharing
    370370static __thread Heap * heapManager CALIGN TLSMODEL;
     371static  __thread bool heapManagerBootFlag CALIGN TLSMODEL = false;
    371372static __thread size_t PAD2 CALIGN TLSMODEL __attribute__(( unused )); // protect further false sharing
    372373
     
    488489                        allocUnfreed = 0;
    489490                        #endif // __CFA_DEBUG__
     491                        heapManagerBootFlag = true;
    490492                } // with
    491493        } // if
     
    499501
    500502        lock( heapMaster.mgrLock );                                                     // protect heapMaster counters
     503
     504        assert( ! heapManagerBootFlag );
    501505
    502506        // get storage for heap manager
     
    514518
    515519void heapManagerDtor() libcfa_public {
     520  if ( unlikely( ! heapManagerBootFlag ) ) return;              // thread never used ?
     521
    516522        lock( heapMaster.mgrLock );
    517523
     
    521527
    522528        #ifdef __STATISTICS__
     529        heapMaster.stats += heapManager->stats;                         // retain this heap's statistics
    523530        heapMaster.threads_exited += 1;
    524531        #endif // __STATISTICS__
     
    526533        // Do not set heapManager to NULL because it is used after Cforall is shutdown but before the program shuts down.
    527534
     535        heapManagerBootFlag = false;
    528536        unlock( heapMaster.mgrLock );
    529537} // heapManagerDtor
     
    535543extern int cfa_main_returned;                                                   // from interpose.cfa
    536544extern "C" {
    537         void memory_startup( void ) {
     545        void memory_startup( void ) {                                           // singleton => called once at start of program
    538546                if ( ! heapMasterBootFlag ) heapManagerCtor();  // sanity check
    539547        } // memory_startup
     
    557565                fclose( stdin ); fclose( stdout );                              // free buffer storage
    558566          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__
    559573
    560574                #ifdef __CFA_DEBUG__
     
    895909#endif // __STATISTICS__
    896910
     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
    897919#define PROLOG( counter, ... ) \
    898920        BOOT_HEAP_MANAGER; \
    899         if ( unlikely( size == 0 ) ||                                           /* 0 BYTE ALLOCATION RETURNS NULL POINTER */ \
     921        if ( \
     922                __NULL_0_ALLOC__ \
    900923                unlikely( size > ULONG_MAX - sizeof(Heap.Storage) ) ) { /* error check */ \
    901924                STAT_0_CNT( counter ); \
  • libcfa/src/iostream.cfa

    r92355883 r2a301ff  
    1010// Created On       : Wed May 27 17:56:53 2015
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Mon Jan  9 09:27:58 2023
    13 // Update Count     : 1361
     12// Last Modified On : Thu Aug 31 11:27:56 2023
     13// Update Count     : 1545
    1414//
    1515
     
    2121#include <float.h>                                                                              // DBL_DIG, LDBL_DIG
    2222#include <complex.h>                                                                    // creal, cimag
    23 //#include <string.h>                                                                   // strlen, strcmp, memcpy
     23//#include <stdio.h>
     24
    2425extern "C" {
    2526extern size_t strlen (const char *__s) __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__pure__)) __attribute__ ((__nonnull__ (1)));
     
    3435#pragma GCC visibility push(default)
    3536
     37
    3638// *********************************** ostream ***********************************
    3739
     
    4345                return os;
    4446        } // ?|?
    45         void ?|?( ostype & os, bool b ) {
    46                 (ostype &)(os | b); ends( os );
    47         } // ?|?
     47        OSTYPE_VOID_IMPL( bool )
    4848
    4949        ostype & ?|?( ostype & os, char c ) {
    5050                fmt( os, "%c", c );
    5151                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 )
    5755
    5856        ostype & ?|?( ostype & os, signed char sc ) {
     
    6159                return os;
    6260        } // ?|?
    63         void ?|?( ostype & os, signed char sc ) {
    64                 (ostype &)(os | sc); ends( os );
    65         } // ?|?
     61        OSTYPE_VOID_IMPL( signed char )
    6662
    6763        ostype & ?|?( ostype & os, unsigned char usc ) {
     
    7066                return os;
    7167        } // ?|?
    72         void ?|?( ostype & os, unsigned char usc ) {
    73                 (ostype &)(os | usc); ends( os );
    74         } // ?|?
     68        OSTYPE_VOID_IMPL( unsigned char )
    7569
    7670        ostype & ?|?( ostype & os, short int si ) {
     
    7973                return os;
    8074        } // ?|?
    81         void & ?|?( ostype & os, short int si ) {
    82                 (ostype &)(os | si); ends( os );
    83         } // ?|?
     75        OSTYPE_VOID_IMPL( short int )
    8476
    8577        ostype & ?|?( ostype & os, unsigned short int usi ) {
     
    8880                return os;
    8981        } // ?|?
    90         void & ?|?( ostype & os, unsigned short int usi ) {
    91                 (ostype &)(os | usi); ends( os );
    92         } // ?|?
     82        OSTYPE_VOID_IMPL( unsigned short int )
    9383
    9484        ostype & ?|?( ostype & os, int i ) {
     
    9787                return os;
    9888        } // ?|?
    99         void & ?|?( ostype & os, int i ) {
    100                 (ostype &)(os | i); ends( os );
    101         } // ?|?
     89        OSTYPE_VOID_IMPL( int )
    10290
    10391        ostype & ?|?( ostype & os, unsigned int ui ) {
     
    10694                return os;
    10795        } // ?|?
    108         void & ?|?( ostype & os, unsigned int ui ) {
    109                 (ostype &)(os | ui); ends( os );
    110         } // ?|?
     96        OSTYPE_VOID_IMPL( unsigned int )
    11197
    11298        ostype & ?|?( ostype & os, long int li ) {
     
    115101                return os;
    116102        } // ?|?
    117         void & ?|?( ostype & os, long int li ) {
    118                 (ostype &)(os | li); ends( os );
    119         } // ?|?
     103        OSTYPE_VOID_IMPL( long int )
    120104
    121105        ostype & ?|?( ostype & os, unsigned long int uli ) {
     
    124108                return os;
    125109        } // ?|?
    126         void & ?|?( ostype & os, unsigned long int uli ) {
    127                 (ostype &)(os | uli); ends( os );
    128         } // ?|?
     110        OSTYPE_VOID_IMPL( unsigned long int )
    129111
    130112        ostype & ?|?( ostype & os, long long int lli ) {
     
    133115                return os;
    134116        } // ?|?
    135         void & ?|?( ostype & os, long long int lli ) {
    136                 (ostype &)(os | lli); ends( os );
    137         } // ?|?
     117        OSTYPE_VOID_IMPL( long long int )
    138118
    139119        ostype & ?|?( ostype & os, unsigned long long int ulli ) {
     
    142122                return os;
    143123        } // ?|?
    144         void & ?|?( ostype & os, unsigned long long int ulli ) {
    145                 (ostype &)(os | ulli); ends( os );
    146         } // ?|?
     124        OSTYPE_VOID_IMPL( unsigned long long int )
    147125
    148126        #if defined( __SIZEOF_INT128__ )
     
    176154                return os;
    177155        } // ?|?
    178         void & ?|?( ostype & os, int128 llli ) {
    179                 (ostype &)(os | llli); ends( os );
    180         } // ?|?
     156        OSTYPE_VOID_IMPL( int128 )
    181157
    182158        ostype & ?|?( ostype & os, unsigned int128 ullli ) {
     
    185161                return os;
    186162        } // ?|?
    187         void & ?|?( ostype & os, unsigned int128 ullli ) {
    188                 (ostype &)(os | ullli); ends( os );
    189         } // ?|?
     163        OSTYPE_VOID_IMPL( unsigned int128 )
    190164        #endif // __SIZEOF_INT128__
    191165
    192         #define PrintWithDP( os, format, val, ... ) \
     166        #define PRINT_WITH_DP( os, format, val, ... ) \
    193167                { \
    194168                        enum { size = 48 }; \
     
    199173                                for ( i; 0 ~ @ ) { \
    200174                                        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 ? */ \
    202177                                } /* for */ \
    203178                        } /* if */ \
     
    206181        ostype & ?|?( ostype & os, float f ) {
    207182                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 )
    214187
    215188        ostype & ?|?( ostype & os, double d ) {
    216189                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 )
    223194
    224195        ostype & ?|?( ostype & os, long double ld ) {
    225196                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 )
    232201
    233202        ostype & ?|?( ostype & os, float _Complex fc ) {
    234203                if ( sepPrt$( os ) ) fmt( os, "%s", sepGetCur$( os ) );
    235204//              os | crealf( fc ) | nonl;
    236                 PrintWithDP( os, "%'g", crealf( fc ) );
    237                 PrintWithDP( os, "%'+g", cimagf( fc ) );
     205                PRINT_WITH_DP( os, "%'g", crealf( fc ) );
     206                PRINT_WITH_DP( os, "%'+g", cimagf( fc ) );
    238207                fmt( os, "i" );
    239208                return os;
    240209        } // ?|?
    241         void & ?|?( ostype & os, float _Complex fc ) {
    242                 (ostype &)(os | fc); ends( os );
    243         } // ?|?
     210        OSTYPE_VOID_IMPL( float _Complex )
    244211
    245212        ostype & ?|?( ostype & os, double _Complex dc ) {
    246213                if ( sepPrt$( os ) ) fmt( os, "%s", sepGetCur$( os ) );
    247214//              os | creal( dc ) | nonl;
    248                 PrintWithDP( os, "%'.*lg", creal( dc ), DBL_DIG );
    249                 PrintWithDP( 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 );
    250217                fmt( os, "i" );
    251218                return os;
    252219        } // ?|?
    253         void & ?|?( ostype & os, double _Complex dc ) {
    254                 (ostype &)(os | dc); ends( os );
    255         } // ?|?
     220        OSTYPE_VOID_IMPL( double _Complex )
    256221
    257222        ostype & ?|?( ostype & os, long double _Complex ldc ) {
    258223                if ( sepPrt$( os ) ) fmt( os, "%s", sepGetCur$( os ) );
    259224//              os | creall( ldc ) || nonl;
    260                 PrintWithDP( os, "%'.*Lg", creall( ldc ), LDBL_DIG );
    261                 PrintWithDP( 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 );
    262227                fmt( os, "i" );
    263228                return os;
    264229        } // ?|?
    265         void & ?|?( ostype & os, long double _Complex ldc ) {
    266                 (ostype &)(os | ldc); ends( os );
    267         } // ?|?
     230        OSTYPE_VOID_IMPL( long double _Complex )
    268231
    269232        ostype & ?|?( ostype & os, const char s[] ) {
    270233                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
    272235                        // opening delimiters, no space after
    273236                        ['('] : Open, ['['] : Open, ['{'] : Open,
     
    284247
    285248          if ( s == 0p ) { fmt( os, "%s", "0p" ); return os; } // null pointer
    286           if ( s[0] == '\0' ) { sepOff( os ); return os; } // null string => no separator
     249          if ( s[0] == '\0' ) { nosep( os ); return os; }       // null string => no leading/trailing separator
    287250
    288251                // first character IS NOT spacing or closing punctuation => add left separator
     
    300263                fmt( os, "%s", s );                                                             // fmt resets seperator, but reset it again
    301264                if ( sepPrt$( os ) && mask[ ch ] != Open && mask[ ch ] != OpenClose ) {
    302                         sepOn( os );
     265                        sep( os );
    303266                } else {
    304                         sepOff( os );
     267                        nosep( os );
    305268                } // if
    306269                if ( ch == '\n' ) setNL$( os, true );                   // check *AFTER* sepPrt$ call above as it resets NL flag
     
    308271//              return write( os, s, len );
    309272        } // ?|?
    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[] ) {
    315276//              if ( sepPrt$( os ) ) fmt( os, "%s", sepGetCur$( os ) );
    316277//              fmt( os, "%ls", s );
     
    319280
    320281// #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[] ) {
    322283//              if ( sepPrt$( os ) ) fmt( os, "%s", sepGetCur$( os ) );
    323284//              fmt( os, "%ls", s );
     
    326287// #endif // ! ( __ARM_ARCH_ISA_ARM == 1 && __ARM_32BIT_STATE == 1 )
    327288
    328 //      ostype & ?|?( ostype & os, const wchar_t * s ) {
     289//      ostype & ?|?( ostype & os, const wchar_t s[] ) {
    329290//              if ( sepPrt$( os ) ) fmt( os, "%s", sepGetCur$( os ) );
    330291//              fmt( os, "%ls", s );
     
    337298                return os;
    338299        } // ?|?
    339         void ?|?( ostype & os, const void * p ) {
    340                 (ostype &)(os | p); ends( os );
    341         } // ?|?
     300        OSTYPE_VOID_IMPL( const void * )
    342301
    343302        // manipulators
     
    351310        } // ?|?
    352311
    353         ostype & sep( ostype & os ) {
    354                 return (ostype &)(os | sepGet( os ));
    355         } // sep
    356 
    357         ostype & sepTuple( ostype & os ) {
    358                 return os | sepGetTuple( os );
    359         } // sepTuple
    360 
    361312        ostype & nl( ostype & os ) {
    362313                (ostype &)(os | '\n');
    363314                setPrt$( os, false );                                                   // turn off
    364315                setNL$( os, true );
    365                 return sepOff( os );                                                    // prepare for next line
     316                return nosep( os );                                                             // prepare for next line
    366317        } // nl
    367318
     
    371322        } // nonl
    372323
     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
    373352        ostype & sepOn( ostype & os ) {
    374353                sepOn( os );                                                                    // call void returning
     
    380359                return os;
    381360        } // sepOff
    382 
    383         ostype & sepEnable( ostype & os ) {
    384                 sepEnable( os );                                                                // call void returning
    385                 return os;
    386         } // sepEnable
    387 
    388         ostype & sepDisable( ostype & os ) {
    389                 sepDisable( os );                                                               // call void returning
    390                 return os;
    391         } // sepDisable
    392 
    393         ostype & nlOn( ostype & os ) {
    394                 nlOn( os );                                                                             // call void returning
    395                 return os;
    396         } // nlOn
    397 
    398         ostype & nlOff( ostype & os ) {
    399                 nlOff( os );                                                                    // call void returning
    400                 return os;
    401         } // nlOff
    402361} // distribution
    403362
     
    442401
    443402// Default prefix for non-decimal prints is 0b, 0, 0x.
    444 #define IntegralFMTImpl( T, IFMTNP, IFMTP ) \
     403#define INTEGRAL_FMT_IMPL( T, IFMTNP, IFMTP ) \
    445404forall( ostype & | basic_ostream( ostype ) ) { \
    446405        ostype & ?|?( ostype & os, _Ostream_Manip(T) f ) { \
     
    508467                fmtstr[star] = '%'; \
    509468\
     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\
    510476                if ( ! f.flags.pc ) {                                                   /* no precision */ \
    511477                        fmtstr[sizeof(IFMTNP)-2] = f.base;                      /* sizeof includes '\0' */ \
     
    519485                return os; \
    520486        } /* ?|? */ \
    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
     490INTEGRAL_FMT_IMPL( signed char,            "      *hh ", "      *.*hh " )
     491INTEGRAL_FMT_IMPL( unsigned char,          "      *hh ", "      *.*hh " )
     492INTEGRAL_FMT_IMPL( signed short int,       "      *h ",  "      *.*h " )
     493INTEGRAL_FMT_IMPL( unsigned short int,     "      *h ",  "      *.*h " )
     494INTEGRAL_FMT_IMPL( signed int,             "      * ",   "      *.* " )
     495INTEGRAL_FMT_IMPL( unsigned int,           "      * ",   "      *.* " )
     496INTEGRAL_FMT_IMPL( signed long int,        "      *l ",  "      *.*l " )
     497INTEGRAL_FMT_IMPL( unsigned long int,      "      *l ",  "      *.*l " )
     498INTEGRAL_FMT_IMPL( signed long long int,   "      *ll ", "      *.*ll " )
     499INTEGRAL_FMT_IMPL( unsigned long long int, "      *ll ", "      *.*ll " )
    536500
    537501
     
    550514                if ( cnt == 1 ) {
    551515                        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 chunks
     516                        nosep( os );                                                            // no seperator between chunks
    553517                } // if
    554518        } else {                                                                                        // print start chunk
     
    595559                else { f.pc = maxdig; f.flags.pc = true; }              // left pad with precision
    596560
    597                 if ( cnt != 0 ) sepOff( os );                                   // no seperator between chunks
     561                if ( cnt != 0 ) nosep( os );                                    // no seperator between chunks
    598562                f.wd = wd;                                                                              // reset f.wd for next chunk
    599563                f.flags.sign = false;                                                   // no leading +/- sign
     
    602566} // base_128
    603567
    604 #define IntegralFMTImpl128( T ) \
     568#define INTEGRAL_FMT_IMPL128( T ) \
    605569forall( ostype & | basic_ostream( ostype ) ) { \
    606570        ostype & ?|?( ostype & os, _Ostream_Manip(T) f ) { \
     
    619583                return os; \
    620584        } /* ?|? */ \
    621         void ?|?( ostype & os, _Ostream_Manip(T) f ) { (ostype &)(os | f); ends( os ); } \
    622 } // distribution
    623 
    624 IntegralFMTImpl128( int128 )
    625 IntegralFMTImpl128( unsigned int128 )
     585        OSTYPE_VOID_IMPL( _Ostream_Manip(T) ) \
     586} // distribution
     587
     588INTEGRAL_FMT_IMPL128( int128 )
     589INTEGRAL_FMT_IMPL128( unsigned int128 )
    626590#endif // __SIZEOF_INT128__
    627591
     
    635599#define SUFFIXES_END (SUFFIXES_START + (int)((sizeof(suffixes) / sizeof(char *) - 1) * 3))
    636600
    637 #define PrintWithDP2( os, format, ... ) \
     601#define PRINT_WITH_DP2( os, format, ... ) \
    638602        { \
    639603                if ( ! f.flags.eng ) { \
    640604                        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 ? */ \
    643608                                if ( i == len ) { \
    644609                                        if ( ! f.flags.left ) { \
     
    676641        }
    677642
    678 #define FloatingPointFMTImpl( T, DFMTNP, DFMTP ) \
     643#define FLOATING_POINT_FMT_IMPL( T, DFMTNP, DFMTP ) \
    679644forall( ostype & | basic_ostream( ostype ) ) { \
    680645        static void eng( T &value, int & pc, int & exp10 ) { \
     
    707672                        fmtstr[sizeof(DFMTNP)-2] = f.base;                      /* sizeof includes '\0' */ \
    708673                        /* printf( "%g %d %s\n", f.val, f.wd, &fmtstr[star] ); */ \
    709                         PrintWithDP2( os, &fmtstr[star], f.wd, f.val ) \
     674                        PRINT_WITH_DP2( os, &fmtstr[star], f.wd, f.val ) \
    710675                } else {                                                                                /* precision */ \
    711676                        fmtstr[sizeof(DFMTP)-2] = f.base;                       /* sizeof includes '\0' */ \
    712677                        /* printf( "%g %d %d %s\n", f.val, f.wd, f.pc, &fmtstr[star] ); */ \
    713                         PrintWithDP2( os, &fmtstr[star], f.wd, f.pc, f.val ) \
     678                        PRINT_WITH_DP2( os, &fmtstr[star], f.wd, f.pc, f.val ) \
    714679                } /* if */ \
    715680                return os; \
    716681        } /* ?|? */ \
    717682\
    718         void ?|?( ostype & os, _Ostream_Manip(T) f ) { (ostype &)(os | f); ends( os ); } \
    719 } // distribution
    720 
    721 FloatingPointFMTImpl( double,      "      * ",  "      *.* " )
    722 FloatingPointFMTImpl( long double, "      *L ", "      *.*L " )
     683        OSTYPE_VOID_IMPL( _Ostream_Manip(T) ) \
     684} // distribution
     685
     686FLOATING_POINT_FMT_IMPL( double,      "      * ",  "      *.* " )
     687FLOATING_POINT_FMT_IMPL( long double, "      *L ", "      *.*L " )
    723688
    724689// *********************************** character ***********************************
     
    751716                return os;
    752717        } // ?|?
    753 
    754         void ?|?( ostype & os, _Ostream_Manip(char) f ) { (ostype &)(os | f); ends( os ); }
     718        OSTYPE_VOID_IMPL( _Ostream_Manip(char) )
    755719} // distribution
    756720
     
    773737                } // if
    774738
    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 ) );
    776741
    777742                #define SFMTNP "% * "
     
    795760                        fmt( os, &fmtstr[star], f.wd, f.pc, f.val );
    796761                } // 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 *) )
    801766} // distribution
    802767
     
    817782                return is;
    818783        } // ?|?
    819         void ?|?( istype & is, bool & b ) {
    820                 (istype &)(is | b); ends( is );
    821         } // ?|?
     784        ISTYPE_VOID_IMPL( bool & )
    822785
    823786        istype & ?|?( istype & is, char & c ) {
     
    831794                return is;
    832795        } // ?|?
    833         void ?|?( istype & is, char & c ) {
    834                 (istype &)(is | c); ends( is );
    835         } // ?|?
     796        ISTYPE_VOID_IMPL( char & )
    836797
    837798        istype & ?|?( istype & is, signed char & sc ) {
     
    839800                return is;
    840801        } // ?|?
    841         void ?|?( istype & is, signed char & sc ) {
    842                 (istype &)(is | sc); ends( is );
    843         } // ?|?
     802        ISTYPE_VOID_IMPL( signed char & )
    844803
    845804        istype & ?|?( istype & is, unsigned char & usc ) {
     
    847806                return is;
    848807        } // ?|?
    849         void ?|?( istype & is, unsigned char & usc ) {
    850                 (istype &)(is | usc); ends( is );
    851         } // ?|?
     808        ISTYPE_VOID_IMPL( unsigned char & )
    852809
    853810        istype & ?|?( istype & is, short int & si ) {
     
    855812                return is;
    856813        } // ?|?
    857         void ?|?( istype & is, short int & si ) {
    858                 (istype &)(is | si); ends( is );
    859         } // ?|?
     814        ISTYPE_VOID_IMPL( short int & )
    860815
    861816        istype & ?|?( istype & is, unsigned short int & usi ) {
     
    863818                return is;
    864819        } // ?|?
    865         void ?|?( istype & is, unsigned short int & usi ) {
    866                 (istype &)(is | usi); ends( is );
    867         } // ?|?
     820        ISTYPE_VOID_IMPL( unsigned short int & )
    868821
    869822        istype & ?|?( istype & is, int & i ) {
     
    871824                return is;
    872825        } // ?|?
    873         void ?|?( istype & is, int & i ) {
    874                 (istype &)(is | i); ends( is );
    875         } // ?|?
     826        ISTYPE_VOID_IMPL( int & )
    876827
    877828        istype & ?|?( istype & is, unsigned int & ui ) {
     
    879830                return is;
    880831        } // ?|?
    881         void ?|?( istype & is, unsigned int & ui ) {
    882                 (istype &)(is | ui); ends( is );
    883         } // ?|?
     832        ISTYPE_VOID_IMPL( unsigned int & )
    884833
    885834        istype & ?|?( istype & is, long int & li ) {
     
    887836                return is;
    888837        } // ?|?
    889         void ?|?( istype & is, long int & li ) {
    890                 (istype &)(is | li); ends( is );
    891         } // ?|?
     838        ISTYPE_VOID_IMPL( long int & )
    892839
    893840        istype & ?|?( istype & is, unsigned long int & ulli ) {
     
    895842                return is;
    896843        } // ?|?
    897         void ?|?( istype & is, unsigned long int & ulli ) {
    898                 (istype &)(is | ulli); ends( is );
    899         } // ?|?
     844        ISTYPE_VOID_IMPL( unsigned long int & )
    900845
    901846        istype & ?|?( istype & is, long long int & lli ) {
     
    903848                return is;
    904849        } // ?|?
    905         void ?|?( istype & is, long long int & lli ) {
    906                 (istype &)(is | lli); ends( is );
    907         } // ?|?
     850        ISTYPE_VOID_IMPL( long long int & )
    908851
    909852        istype & ?|?( istype & is, unsigned long long int & ulli ) {
     
    911854                return is;
    912855        } // ?|?
    913         void & ?|?( istype & is, unsigned long long int & ulli ) {
    914                 (istype &)(is | ulli); ends( is );
    915         } // ?|?
     856        ISTYPE_VOID_IMPL( unsigned long long int & )
    916857
    917858        #if defined( __SIZEOF_INT128__ )
     
    919860                return (istype &)(is | (unsigned int128 &)llli);
    920861        } // ?|?
    921         void ?|?( istype & is, int128 & llli ) {
    922                 (istype &)(is | llli); ends( is );
    923         } // ?|?
     862        ISTYPE_VOID_IMPL( int128 & )
    924863
    925864        istype & ?|?( istype & is, unsigned int128 & ullli ) {
     
    938877                return is;
    939878        } // ?|?
    940         void ?|?( istype & is, unsigned int128 & ullli ) {
    941                 (istype &)(is | ullli); ends( is );
    942         } // ?|?
     879        ISTYPE_VOID_IMPL( unsigned int128 & )
    943880        #endif // __SIZEOF_INT128__
    944881
     
    947884                return is;
    948885        } // ?|?
    949         void ?|?( istype & is, float & f ) {
    950                 (istype &)(is | f); ends( is );
    951         } // ?|?
     886        ISTYPE_VOID_IMPL( float & )
    952887
    953888        istype & ?|?( istype & is, double & d ) {
     
    955890                return is;
    956891        } // ?|?
    957         void ?|?( istype & is, double & d ) {
    958                 (istype &)(is | d); ends( is );
    959         } // ?|?
     892        ISTYPE_VOID_IMPL( double & )
    960893
    961894        istype & ?|?( istype & is, long double & ld ) {
     
    963896                return is;
    964897        } // ?|?
    965         void ?|?( istype & is, long double & ld ) {
    966                 (istype &)(is | ld); ends( is );
    967         } // ?|?
     898        ISTYPE_VOID_IMPL( long double & )
    968899
    969900        istype & ?|?( istype & is, float _Complex & fc ) {
     
    973904                return is;
    974905        } // ?|?
    975         void ?|?( istype & is, float _Complex & fc ) {
    976                 (istype &)(is | fc); ends( is );
    977         } // ?|?
     906        ISTYPE_VOID_IMPL( float _Complex & )
    978907
    979908        istype & ?|?( istype & is, double _Complex & dc ) {
     
    983912                return is;
    984913        } // ?|?
    985         void ?|?( istype & is, double _Complex & dc ) {
    986                 (istype &)(is | dc); ends( is );
    987         } // ?|?
     914        ISTYPE_VOID_IMPL( double _Complex & )
    988915
    989916        istype & ?|?( istype & is, long double _Complex & ldc ) {
     
    993920                return is;
    994921        } // ?|?
    995         void ?|?( istype & is, long double _Complex & ldc ) {
    996                 (istype &)(is | ldc); ends( is );
    997         } // ?|?
     922        ISTYPE_VOID_IMPL( long double _Complex & )
    998923
    999924        // istype & ?|?( istype & is, const char fmt[] ) {
     
    1002927        // } // ?|?
    1003928
    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 * )
    1011934
    1012935        // manipulators
     
    1014937                return manip( is );
    1015938        } // ?|?
     939
    1016940        void ?|?( istype & is, istype & (* manip)( istype & ) ) {
    1017941                manip( is ); ends( is );
     
    1020944        istype & nl( istype & is ) {
    1021945                fmt( is, "%*[^\n]" );                                                   // ignore characters to newline
     946                if ( ! eof( is ) && getANL$( is ) ) fmt( is, "%*c" ); // read newline
    1022947                return is;
    1023948        } // nl
     
    1038963forall( istype & | basic_istream( istype ) ) {
    1039964        istype & ?|?( istype & is, _Istream_Cstr f ) {
    1040                 // skip xxx
     965                // skip
    1041966                if ( ! f.s ) {
    1042967                        // printf( "skip %s %d\n", f.scanset, f.wd );
    1043                         if ( f.wd == -1 ) fmt( is, f.scanset, "" );             // no input arguments
     968                        if ( f.wd == -1 ) fmt( is, f.scanset, "" );     // no input arguments
    1044969                        else for ( f.wd ) fmt( is, "%*c" );
    1045970                        return is;
    1046971                } // if
     972
     973                const char * scanset = f.scanset;
     974                if ( f.flags.delimit ) scanset = f.delimit;             // getline ?
     975
    1047976                size_t len = 0;
    1048                 if ( f.scanset ) len = strlen( f.scanset );
     977                if ( scanset ) len = strlen( scanset );
    1049978                char fmtstr[len + 16];
    1050979                int start = 1;
     
    1052981                if ( f.flags.ignore ) { fmtstr[1] = '*'; start += 1; }
    1053982                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
    1056986                        fmtstr[start] = 's'; fmtstr[start + 1] = '\0';
    1057987                        // 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 )
    10751014
    10761015        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 ) \
    10861023forall( istype & | basic_istream( istype ) ) { \
    10871024        istype & ?|?( istype & is, _Istream_Manip(T) f ) { \
     
    10971034                return is; \
    10981035        } /* ?|? */ \
    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
     1039INPUT_FMT_IMPL( signed char, "hhi" )
     1040INPUT_FMT_IMPL( unsigned char, "hhi" )
     1041INPUT_FMT_IMPL( signed short int, "hi" )
     1042INPUT_FMT_IMPL( unsigned short int, "hi" )
     1043INPUT_FMT_IMPL( signed int, "i" )
     1044INPUT_FMT_IMPL( unsigned int, "i" )
     1045INPUT_FMT_IMPL( signed long int, "li" )
     1046INPUT_FMT_IMPL( unsigned long int, "li" )
     1047INPUT_FMT_IMPL( signed long long int, "lli" )
     1048INPUT_FMT_IMPL( unsigned long long int, "lli" )
     1049
     1050INPUT_FMT_IMPL( float, "f" )
     1051INPUT_FMT_IMPL( double, "lf" )
     1052INPUT_FMT_IMPL( long double, "Lf" )
    11181053
    11191054forall( istype & | basic_istream( istype ) ) {
     
    11271062                return is;
    11281063        } // ?|?
    1129         void ?|?( istype & is, _Istream_Manip(float _Complex) fc ) {
    1130                 (istype &)(is | fc); ends( is );
    1131         } // ?|?
     1064        ISTYPE_VOID_IMPL( _Istream_Manip(float _Complex) )
    11321065
    11331066        istype & ?|?( istype & is, _Istream_Manip(double _Complex) dc ) {
     
    11401073                return is;
    11411074        } // ?|?
    1142         void ?|?( istype & is, _Istream_Manip(double _Complex) dc ) {
    1143                 (istype &)(is | dc); ends( is );
    1144         } // ?|?
     1075        ISTYPE_VOID_IMPL( _Istream_Manip(double _Complex) )
    11451076
    11461077        istype & ?|?( istype & is, _Istream_Manip(long double _Complex) ldc ) {
     
    11531084                return is;
    11541085        } // ?|?
    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
    11591089
    11601090// Local Variables: //
  • libcfa/src/iostream.hfa

    r92355883 r2a301ff  
    1010// Created On       : Wed May 27 17:56:53 2015
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Thu Jun 15 22:34:31 2023
    13 // Update Count     : 411
     12// Last Modified On : Thu Aug 31 10:55:35 2023
     13// Update Count     : 544
    1414//
    1515
     
    1717
    1818#include "iterator.hfa"
    19 
     19#include "Exception.hfa"
    2020
    2121// *********************************** ostream ***********************************
    22 
    2322
    2423forall( ostype & )
     
    3029        const char * sepGetCur$( ostype & );                            // get current separator string
    3130        void sepSetCur$( ostype &, const char [] );                     // set current separator string
    32         bool getNL$( ostype & );                                                        // check newline
    33         void setNL$( ostype &, bool );                                          // saw newline
     31        bool getNL$( ostype & );                                                        // get newline
     32        bool setNL$( ostype &, bool );                                          // set newline
    3433        bool getANL$( ostype & );                                                       // get auto newline (on/off)
     34        bool setANL$( ostype &, bool );                                         // set auto newline (on/off), and return previous state
    3535        bool getPrt$( ostype & );                                                       // get fmt called in output cascade
    36         void setPrt$( ostype &, bool );                                         // set fmt called in output cascade
     36        bool setPrt$( ostype &, bool );                                         // set fmt called in output cascade
    3737        // public
    38         void sepOn( ostype & );                                                         // turn separator state on
    39         void sepOff( ostype & );                                                        // turn separator state off
    40         bool sepDisable( ostype & );                                            // set default state to off, and return previous state
    41         bool sepEnable( ostype & );                                                     // set default state to on, and return previous state
    4238        void nlOn( ostype & );                                                          // turn auto-newline state on
    4339        void nlOff( ostype & );                                                         // turn auto-newline state off
    4440
     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
    4545        const char * sepGet( ostype & );                                        // get separator string
    4646        void sepSet( ostype &, const char [] );                         // set separator to string (15 character maximum)
     
    7474// implement writable for intrinsic types
    7575
     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
    7682forall( ostype & | basic_ostream( ostype ) ) {
    7783        ostype & ?|?( ostype &, bool );
    78         void ?|?( ostype &, bool );
     84        OSTYPE_VOID( bool );
    7985
    8086        ostype & ?|?( ostype &, char );
    81         void ?|?( ostype &, char );
     87        OSTYPE_VOID( char );
    8288        ostype & ?|?( ostype &, signed char );
    83         void ?|?( ostype &, signed char );
     89        OSTYPE_VOID( signed char );
    8490        ostype & ?|?( ostype &, unsigned char );
    85         void ?|?( ostype &, unsigned char );
     91        OSTYPE_VOID( unsigned char );
    8692
    8793        ostype & ?|?( ostype &, short int );
    88         void ?|?( ostype &, short int );
     94        OSTYPE_VOID( short int );
    8995        ostype & ?|?( ostype &, unsigned short int );
    90         void ?|?( ostype &, unsigned short int );
     96        OSTYPE_VOID( unsigned short int );
    9197        ostype & ?|?( ostype &, int );
    92         void ?|?( ostype &, int );
     98        OSTYPE_VOID( int );
    9399        ostype & ?|?( ostype &, unsigned int );
    94         void ?|?( ostype &, unsigned int );
     100        OSTYPE_VOID( unsigned int );
    95101        ostype & ?|?( ostype &, long int );
    96         void ?|?( ostype &, long int );
     102        OSTYPE_VOID( long int );
    97103        ostype & ?|?( ostype &, long long int );
    98         void ?|?( ostype &, long long int );
     104        OSTYPE_VOID( long long int );
    99105        ostype & ?|?( ostype &, unsigned long int );
    100         void ?|?( ostype &, unsigned long int );
     106        OSTYPE_VOID( unsigned long int );
    101107        ostype & ?|?( ostype &, unsigned long long int );
    102         void ?|?( ostype &, unsigned long long int );
     108        OSTYPE_VOID( unsigned long long int );
    103109        #if defined( __SIZEOF_INT128__ )
    104110        ostype & ?|?( ostype &, int128 );
    105         void ?|?( ostype &, int128 );
     111        OSTYPE_VOID( int128 );
    106112        ostype & ?|?( ostype &, unsigned int128 );
    107         void ?|?( ostype &, unsigned int128 );
     113        OSTYPE_VOID( unsigned int128 );
    108114        #endif // __SIZEOF_INT128__
    109115
    110116        ostype & ?|?( ostype &, float );
    111         void ?|?( ostype &, float );
     117        OSTYPE_VOID( float );
    112118        ostype & ?|?( ostype &, double );
    113         void ?|?( ostype &, double );
     119        OSTYPE_VOID( double );
    114120        ostype & ?|?( ostype &, long double );
    115         void ?|?( ostype &, long double );
     121        OSTYPE_VOID( long double );
    116122
    117123        ostype & ?|?( ostype &, float _Complex );
    118         void ?|?( ostype &, float _Complex );
     124        OSTYPE_VOID( float _Complex );
    119125        ostype & ?|?( ostype &, double _Complex );
    120         void ?|?( ostype &, double _Complex );
     126        OSTYPE_VOID( double _Complex );
    121127        ostype & ?|?( ostype &, long double _Complex );
    122         void ?|?( ostype &, long double _Complex );
     128        OSTYPE_VOID( long double _Complex );
    123129
    124130        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 [] );
    127133        #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 [] );
    129135        #endif // ! ( __ARM_ARCH_ISA_ARM == 1 && __ARM_32BIT_STATE == 1 )
    130         // ostype & ?|?( ostype &, const wchar_t * );
     136        // ostype & ?|?( ostype &, const wchar_t [] );
    131137        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 );
    133143
    134144        // manipulators
    135145        ostype & ?|?( ostype &, ostype & (*)( ostype & ) );
    136         void ?|?( ostype &, ostype & (*)( ostype & ) );
     146        OSTYPE_VOID( ostype & (*)( ostype & ) );
     147
    137148        ostype & nl( ostype & );
    138149        ostype & nonl( ostype & );
     150        ostype & nlOn( ostype & );
     151        ostype & nlOff( ostype & );
     152
     153        ostype & sepVal( ostype & );
     154        ostype & sepTupleVal( ostype & );
    139155        ostype & sep( ostype & );
    140         ostype & sepTuple( ostype & );
     156        ostype & nosep( ostype & );
    141157        ostype & sepOn( ostype & );
    142158        ostype & sepOff( ostype & );
    143         ostype & sepDisable( ostype & );
    144         ostype & sepEnable( ostype & );
    145         ostype & nlOn( ostype & );
    146         ostype & nlOff( ostype & );
    147159} // distribution
    148160
     
    188200// initialized explicitly shall be initialized implicitly the same as objects that have static storage duration.***
    189201
    190 #define IntegralFMTDecl( T, CODE ) \
     202#define INTEGRAL_FMT_DECL( T, CODE ) \
    191203static inline { \
    192204        _Ostream_Manip(T) bin( T val ) { return (_Ostream_Manip(T))@{ val, 1, 0, 'b', { .all : 0 } }; } \
     
    206218forall( ostype & | basic_ostream( ostype ) ) { \
    207219        ostype & ?|?( ostype & os, _Ostream_Manip(T) f ); \
    208         void ?|?( ostype & os, _Ostream_Manip(T) f ); \
     220        OSTYPE_VOID( _Ostream_Manip(T) ); \
    209221} // ?|?
    210222
    211 IntegralFMTDecl( signed char, 'd' )
    212 IntegralFMTDecl( unsigned char, 'u' )
    213 IntegralFMTDecl( signed short int, 'd' )
    214 IntegralFMTDecl( unsigned short int, 'u' )
    215 IntegralFMTDecl( signed int, 'd' )
    216 IntegralFMTDecl( unsigned int, 'u' )
    217 IntegralFMTDecl( signed long int, 'd' )
    218 IntegralFMTDecl( unsigned long int, 'u' )
    219 IntegralFMTDecl( signed long long int, 'd' )
    220 IntegralFMTDecl( unsigned long long int, 'u' )
     223INTEGRAL_FMT_DECL( signed char, 'd' )
     224INTEGRAL_FMT_DECL( unsigned char, 'u' )
     225INTEGRAL_FMT_DECL( signed short int, 'd' )
     226INTEGRAL_FMT_DECL( unsigned short int, 'u' )
     227INTEGRAL_FMT_DECL( signed int, 'd' )
     228INTEGRAL_FMT_DECL( unsigned int, 'u' )
     229INTEGRAL_FMT_DECL( signed long int, 'd' )
     230INTEGRAL_FMT_DECL( unsigned long int, 'u' )
     231INTEGRAL_FMT_DECL( signed long long int, 'd' )
     232INTEGRAL_FMT_DECL( unsigned long long int, 'u' )
    221233#if defined( __SIZEOF_INT128__ )
    222 IntegralFMTDecl( int128, 'd' )
    223 IntegralFMTDecl( unsigned int128, 'u' )
     234INTEGRAL_FMT_DECL( int128, 'd' )
     235INTEGRAL_FMT_DECL( unsigned int128, 'u' )
    224236#endif // __SIZEOF_INT128__
    225237
     
    227239
    228240// Default suffix for values with no fraction is "."
    229 #define FloatingPointFMTDecl( T ) \
     241#define FLOATING_POINT_FMT_DECL( T ) \
    230242static inline { \
    231243        _Ostream_Manip(T) hex( T val ) { return (_Ostream_Manip(T))@{ val, 1, 0, 'a', { .all : 0 } }; } \
     
    251263forall( ostype & | basic_ostream( ostype ) ) { \
    252264        ostype & ?|?( ostype & os, _Ostream_Manip(T) f ); \
    253         void ?|?( ostype & os, _Ostream_Manip(T) f ); \
     265        OSTYPE_VOID( _Ostream_Manip(T) ); \
    254266} // ?|?
    255267
    256 FloatingPointFMTDecl( double )
    257 FloatingPointFMTDecl( long double )
     268FLOATING_POINT_FMT_DECL( double )
     269FLOATING_POINT_FMT_DECL( long double )
    258270
    259271// *********************************** character ***********************************
     
    271283forall( ostype & | basic_ostream( ostype ) ) {
    272284        ostype & ?|?( ostype & os, _Ostream_Manip(char) f );
    273         void ?|?( ostype & os, _Ostream_Manip(char) f );
     285        OSTYPE_VOID( _Ostream_Manip(char) ); \
    274286} // ?|?
    275287
     
    289301forall( ostype & | basic_ostream( ostype ) ) {
    290302        ostype & ?|?( ostype & os, _Ostream_Manip(const char *) f );
    291         void ?|?( ostype & os, _Ostream_Manip(const char *) f );
     303        OSTYPE_VOID( _Ostream_Manip(const char *) ); \
    292304} // ?|?
    293305
    294 
    295306// *********************************** istream ***********************************
    296307
     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        } // ?|?
    297313
    298314forall( istype & )
     
    300316        // private
    301317        bool getANL$( istype & );                                                       // get scan newline (on/off)
     318        bool setANL$( istype &, bool );                                         // set scan newline (on/off)
    302319        // public
    303320        void nlOn( istype & );                                                          // read newline
     
    325342forall( istype & | basic_istream( istype ) ) {
    326343        istype & ?|?( istype &, bool & );
    327         void ?|?( istype &, bool & );
     344        ISTYPE_VOID( bool & );
    328345
    329346        istype & ?|?( istype &, char & );
    330         void ?|?( istype &, char & );
     347        ISTYPE_VOID( char & );
    331348        istype & ?|?( istype &, signed char & );
    332         void ?|?( istype &, signed char & );
     349        ISTYPE_VOID( signed char & );
    333350        istype & ?|?( istype &, unsigned char & );
    334         void ?|?( istype &, unsigned char & );
     351        ISTYPE_VOID( unsigned char & );
    335352
    336353        istype & ?|?( istype &, short int & );
    337         void ?|?( istype &, short int & );
     354        ISTYPE_VOID( short int & );
    338355        istype & ?|?( istype &, unsigned short int & );
    339         void ?|?( istype &, unsigned short int & );
     356        ISTYPE_VOID( unsigned short int & );
    340357        istype & ?|?( istype &, int & );
    341         void ?|?( istype &, int & );
     358        ISTYPE_VOID( int & );
    342359        istype & ?|?( istype &, unsigned int & );
    343         void ?|?( istype &, unsigned int & );
     360        ISTYPE_VOID( unsigned int & );
    344361        istype & ?|?( istype &, long int & );
    345         void ?|?( istype &, long int & );
     362        ISTYPE_VOID( long int & );
    346363        istype & ?|?( istype &, unsigned long int & );
    347         void ?|?( istype &, unsigned long int & );
     364        ISTYPE_VOID( unsigned long int & );
    348365        istype & ?|?( istype &, long long int & );
    349         void ?|?( istype &, long long int & );
     366        ISTYPE_VOID( long long int & );
    350367        istype & ?|?( istype &, unsigned long long int & );
    351         void ?|?( istype &, unsigned long long int & );
     368        ISTYPE_VOID( unsigned long long int & );
    352369        #if defined( __SIZEOF_INT128__ )
    353370        istype & ?|?( istype &, int128 & );
    354         void ?|?( istype &, int128 & );
     371        ISTYPE_VOID( int128 & );
    355372        istype & ?|?( istype &, unsigned int128 & );
    356         void ?|?( istype &, unsigned int128 & );
     373        ISTYPE_VOID( unsigned int128 & );
    357374        #endif // __SIZEOF_INT128__
    358375
    359376        istype & ?|?( istype &, float & );
    360         void ?|?( istype &, float & );
     377        ISTYPE_VOID( float & );
    361378        istype & ?|?( istype &, double & );
    362         void ?|?( istype &, double & );
     379        ISTYPE_VOID( double & );
    363380        istype & ?|?( istype &, long double & );
    364         void ?|?( istype &, long double & );
     381        ISTYPE_VOID( long double & );
    365382
    366383        istype & ?|?( istype &, float _Complex & );
    367         void ?|?( istype &, float _Complex & );
     384        ISTYPE_VOID( float _Complex & );
    368385        istype & ?|?( istype &, double _Complex & );
    369         void ?|?( istype &, double _Complex & );
     386        ISTYPE_VOID( double _Complex & );
    370387        istype & ?|?( istype &, long double _Complex & );
    371         void ?|?( istype &, long double _Complex & );
     388        ISTYPE_VOID( long double _Complex & );
    372389
    373390//      istype & ?|?( istype &, const char [] );
    374         istype & ?|?( istype &, char [] );
    375         void ?|?( istype &, char [] );
     391//      istype & ?|?( istype &, char [] );
     392//      ISTYPE_VOID( char [] );
    376393
    377394        // manipulators
    378395        istype & ?|?( istype &, istype & (*)( istype & ) );
    379         void ?|?( istype &, istype & (*)( istype & ) );
     396        ISTYPE_VOID( istype & (*)( istype & ) );
    380397        istype & nl( istype & is );
    381398        istype & nlOn( istype & );
     
    383400} // distribution
    384401
     402// *********************************** exceptions ***********************************
     403
     404ExceptionDecl( cstring_length );
     405
    385406// *********************************** manipulators ***********************************
    386407
    387 struct _Istream_Cstr {
    388         char * s;
    389         const char * scanset;
     408struct _Istream_str_base {
     409        union {
     410                const char * scanset;
     411                char delimit[2];
     412        };
    390413        int wd;                                                                                         // width
    391414        union {
     
    394417                        unsigned char ignore:1;                                         // do not change input argument
    395418                        unsigned char inex:1;                                           // include/exclude characters in scanset
     419                        unsigned char delimit:1;                                        // delimit character
     420                        unsigned char rwd:1;                                            // read width
    396421                } flags;
    397422        };
     423}; // _Istream_str_base
     424
     425struct _Istream_Cstr {
     426        char * s;
     427        inline _Istream_str_base;
    398428}; // _Istream_Cstr
    399429
    400430static 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; }
    404442        _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 } }; }
    406443        _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} } }; }
    408445        _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; }
    411446} // distribution
    412447forall( istype & | basic_istream( istype ) ) {
    413448        istype & ?|?( istype & is, _Istream_Cstr f );
    414         void ?|?( istype & is, _Istream_Cstr f );
     449        ISTYPE_VOID( _Istream_Cstr );
    415450}
    416451
     
    425460forall( istype & | basic_istream( istype ) ) {
    426461        istype & ?|?( istype & is, _Istream_Char f );
    427         void ?|?( istype & is, _Istream_Char f );
     462        ISTYPE_VOID( _Istream_Char );
    428463}
    429464
     
    435470}; // _Istream_Manip
    436471
    437 #define InputFMTDecl( T ) \
     472#define INPUT_FMT_DECL( T ) \
    438473static inline { \
    439474        _Istream_Manip(T) ignore( const T & val ) { return (_Istream_Manip(T))@{ (T &)val, -1, true }; } \
    440475        _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; } \
    443478} /* distribution */ \
    444479forall( istype & | basic_istream( istype ) ) { \
    445480        istype & ?|?( istype & is, _Istream_Manip(T) f ); \
    446         void ?|?( istype & is, _Istream_Manip(T) f ); \
     481        ISTYPE_VOID( _Istream_Manip(T) ); \
    447482} // ?|?
    448483
    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 
     484INPUT_FMT_DECL( signed char )
     485INPUT_FMT_DECL( unsigned char )
     486INPUT_FMT_DECL( signed short int )
     487INPUT_FMT_DECL( unsigned short int )
     488INPUT_FMT_DECL( signed int )
     489INPUT_FMT_DECL( unsigned int )
     490INPUT_FMT_DECL( signed long int )
     491INPUT_FMT_DECL( unsigned long int )
     492INPUT_FMT_DECL( signed long long int )
     493INPUT_FMT_DECL( unsigned long long int )
     494
     495INPUT_FMT_DECL( float )
     496INPUT_FMT_DECL( double )
     497INPUT_FMT_DECL( long double )
     498
     499INPUT_FMT_DECL( float _Complex )
     500INPUT_FMT_DECL( double _Complex )
     501INPUT_FMT_DECL( long double _Complex )
    468502
    469503// *********************************** time ***********************************
    470 
    471504
    472505#include <time_t.hfa>                                                                   // Duration (constructors) / Time (constructors)
     
    474507forall( ostype & | ostream( ostype ) ) {
    475508        ostype & ?|?( ostype & os, Duration dur );
    476         void ?|?( ostype & os, Duration dur );
     509        OSTYPE_VOID( Duration );
    477510        ostype & ?|?( ostype & os, Time time );
    478         void ?|?( ostype & os, Time time );
     511        OSTYPE_VOID( Time );
    479512} // distribution
    480513
  • libcfa/src/parseargs.cfa

    r92355883 r2a301ff  
    230230}
    231231
    232 void print_args_usage(cfa_option options[], size_t opt_count, const char * usage, bool error)  __attribute__ ((noreturn)) {
     232void print_args_usage(cfa_option options[], const size_t opt_count, const char * usage, bool error)  __attribute__ ((noreturn)) {
    233233        const array( cfa_option, opt_count ) & arr = (const array( cfa_option, opt_count ) &) *options;
    234234        usage(cfa_args_argv[0], arr, usage, error ? stderr : stdout);
    235235}
    236236
    237 void print_args_usage(int , char * argv[], cfa_option options[], size_t opt_count, const char * usage, bool error)  __attribute__ ((noreturn)) {
     237void print_args_usage(int , char * argv[], cfa_option options[], const size_t opt_count, const char * usage, bool error)  __attribute__ ((noreturn)) {
    238238        const array( cfa_option, opt_count ) & arr = (const array( cfa_option, opt_count ) &) *options;
    239239        usage(argv[0], arr, usage, error ? stderr : stdout);
  • libcfa/src/parseconfig.cfa

    r92355883 r2a301ff  
    1616#pragma GCC visibility push(default)
    1717
     18
    1819// *********************************** exceptions ***********************************
    1920
    20 
    21 // TODO: Add names of missing config entries to exception (see further below)
    22 vtable(Missing_Config_Entries) Missing_Config_Entries_vt;
    2321
    2422[ void ] ?{}( & Missing_Config_Entries this, unsigned int num_missing ) {
     
    2927// TODO: use string interface when it's ready (and implement exception msg protocol)
    3028[ 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.");
    3230} // msg
    3331
    34 
    35 vtable(Parse_Failure) Parse_Failure_vt;
    3632
    3733[ void ] ?{}( & Parse_Failure this, [] char failed_key, [] char failed_value ) {
     
    5450}
    5551
    56 
    57 vtable(Validation_Failure) Validation_Failure_vt;
    5852
    5953[ void ] ?{}( & Validation_Failure this, [] char failed_key, [] char failed_value ) {
     
    112106
    113107
    114 static [ bool ] comments( & ifstream in, [] char name ) {
     108static [ bool ] comments( & ifstream in, size_t size, [] char name ) {
    115109        while () {
    116                 in | name;
     110                in | wdi( size, name );
    117111          if ( eof( in ) ) return true;
    118112          if ( name[0] != '#' ) return false;
     
    136130                        // NOTE: Must add check to see if already read in value for this key,
    137131                        // 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 );
    140134
    141135                        add_kv_pair( *kv_pairs, key, value );
  • libcfa/src/parseconfig.hfa

    r92355883 r2a301ff  
    22
    33#include <math.trait.hfa>
     4#include <Exception.hfa>
    45
    56
     
    6263
    6364
    64 exception Missing_Config_Entries {
     65ExceptionDecl( Missing_Config_Entries,
    6566        unsigned int num_missing;
    66 };
     67);
    6768
    6869[ void ] msg( * Missing_Config_Entries ex );
    6970
    70 exception Parse_Failure {
     71ExceptionDecl( Parse_Failure,
    7172        * char failed_key;
    7273        * char failed_value;
    73 };
     74);
    7475
    7576[ void ] msg( * Parse_Failure ex );
    7677
    77 exception Validation_Failure {
     78ExceptionDecl( Validation_Failure,
    7879        * char failed_key;
    7980        * char failed_value;
    80 };
     81);
    8182
    8283[ void ] msg( * Validation_Failure ex );
  • libcfa/src/rational.cfa

    r92355883 r2a301ff  
    1010// Created On       : Wed Apr  6 17:54:28 2016
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Mon Jun  5 22:49:06 2023
    13 // Update Count     : 196
     12// Last Modified On : Tue Jul 18 11:07:10 2023
     13// Update Count     : 197
    1414//
    1515
     
    206206                        return os | r.numerator | '/' | r.denominator;
    207207                } // ?|?
    208 
    209                 void ?|?( ostype & os, rational(T) r ) {
    210                         (ostype &)(os | r); ends( os );
    211                 } // ?|?
     208                OSTYPE_VOID_IMPL( rational(T) )
    212209        } // distribution
    213210} // distribution
  • libcfa/src/rational.hfa

    r92355883 r2a301ff  
    1212// Created On       : Wed Apr  6 17:56:25 2016
    1313// Last Modified By : Peter A. Buhr
    14 // Last Modified On : Mon Jun  5 22:49:05 2023
    15 // Update Count     : 119
     14// Last Modified On : Tue Jul 18 11:08:24 2023
     15// Update Count     : 121
    1616//
    1717
     
    7878        forall( ostype & | ostream( ostype ) | { ostype & ?|?( ostype &, T ); } ) {
    7979                ostype & ?|?( ostype &, rational(T) );
    80                 void ?|?( ostype &, rational(T) );
     80                OSTYPE_VOID( rational(T) );
    8181        } // distribution
    8282} // distribution
  • libcfa/src/stdlib.cfa

    r92355883 r2a301ff  
    1010// Created On       : Thu Jan 28 17:10:29 2016
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Thu Feb 16 16:31:34 2023
    13 // Update Count     : 633
     12// Last Modified On : Mon Aug 14 18:22:36 2023
     13// Update Count     : 642
    1414//
    1515
     
    6565//---------------------------------------
    6666
    67 float _Complex strto( const char sptr[], char ** eptr ) {
     67forall( T | { T strto( const char sptr[], char * eptr[], int ); } )
     68T 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
     78float _Complex strto( const char sptr[], char * eptr[] ) {
    6879        float re, im;
    6980        char * eeptr;
     
    7687} // strto
    7788
    78 double _Complex strto( const char sptr[], char ** eptr ) {
     89double _Complex strto( const char sptr[], char * eptr[] ) {
    7990        double re, im;
    8091        char * eeptr;
     
    8798} // strto
    8899
    89 long double _Complex strto( const char sptr[], char ** eptr ) {
     100long double _Complex strto( const char sptr[], char * eptr[] ) {
    90101        long double re, im;
    91102        char * eeptr;
  • libcfa/src/stdlib.hfa

    r92355883 r2a301ff  
    1010// Created On       : Thu Jan 28 17:12:35 2016
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Thu Feb  2 11:30:04 2023
    13 // Update Count     : 766
     12// Last Modified On : Mon Aug 14 18:19:12 2023
     13// Update Count     : 777
    1414//
    1515
     
    1919#include "bits/align.hfa"                                                               // libAlign
    2020#include "bits/random.hfa"                                                              // prng
     21#include <Exception.hfa>
     22#include <heap.hfa>
    2123
    2224#include <stdlib.h>                                                                             // *alloc, strto*, ato*
    23 #include <heap.hfa>
    24 
     25#include <errno.h>
    2526
    2627// Reduce includes by explicitly defining these routines.
     
    294295
    295296static 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
     309float _Complex strto( const char sptr[], char * eptr[] );
     310double _Complex strto( const char sptr[], char * eptr[] );
     311long double _Complex strto( const char sptr[], char * eptr[] );
     312
     313ExceptionDecl( out_of_range );
     314ExceptionDecl( invalid_argument );
     315
     316forall( T | { T strto( const char sptr[], char * eptr[], int ); } )
     317T convert( const char sptr[] );
    311318
    312319static inline {
     
    454461} // distribution
    455462
     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
    456470// Concurrent Pseudo Random-Number Generator : generate repeatable sequence of values that appear random.
    457471//
  • libcfa/src/strstream.cfa

    r92355883 r2a301ff  
    1010// Created On       : Thu Apr 22 22:24:35 2021
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Sun Oct 10 16:13:20 2021
    13 // Update Count     : 101
     12// Last Modified On : Fri Aug 18 10:42:49 2023
     13// Update Count     : 112
    1414//
    1515
     
    3232
    3333// private
     34inline bool getNL$( ostrstream & os ) { return os.sawNL$; }
     35inline bool setNL$( ostrstream & os, bool state ) { bool temp = os.sawNL$; os.sawNL$ = state; return temp; }
     36inline bool getANL$( ostrstream & os ) { return os.nlOnOff$; }
     37inline bool setANL$( ostrstream & os, bool state ) { bool temp = os.nlOnOff$; os.nlOnOff$ = state; return temp; }
    3438inline bool sepPrt$( ostrstream & os ) { setNL$( os, false ); return os.sepOnOff$; }
    3539inline void sepReset$( ostrstream & os ) { os.sepOnOff$ = os.sepDefault$; }
     
    3741inline const char * sepGetCur$( ostrstream & os ) { return os.sepCur$; }
    3842inline 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$; }
    4243inline bool getPrt$( ostrstream & os ) { return os.prt$; }
    43 inline void setPrt$( ostrstream & os, bool state ) { os.prt$ = state; }
     44inline bool setPrt$( ostrstream & os, bool state ) { bool temp = os.prt$; os.prt$ = state; return temp; }
    4445
    4546// public
     47void nlOn( ostrstream & os ) { os.nlOnOff$ = true; }
     48void nlOff( ostrstream & os ) { os.nlOnOff$ = false; }
     49
    4650void ?{}( ostrstream & os, char buf[], size_t size ) {
    4751        os.buf$ = buf;
     
    5862} // ?{}
    5963
    60 void sepOn( ostrstream & os ) { os.sepOnOff$ = ! getNL$( os ); }
    61 void sepOff( ostrstream & os ) { os.sepOnOff$ = false; }
     64void sep( ostrstream & os ) { os.sepOnOff$ = ! getNL$( os ); }
     65void nosep( ostrstream & os ) { os.sepOnOff$ = false; }
    6266
    63 bool sepDisable( ostrstream & os ) {
     67bool 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
     74bool sepOff( ostrstream & os ) {
    6475        bool temp = os.sepDefault$;
    6576        os.sepDefault$ = false;
    6677        sepReset$( os );
    6778        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
    7980
    8081const char * sepGet( ostrstream & os ) { return os.separator$; }
     
    132133// private
    133134bool getANL$( istrstream & is ) { return is.nlOnOff$; }
     135bool setANL$( istrstream & is, bool state ) { bool temp = is.nlOnOff$; is.nlOnOff$ = state; return temp;  }
    134136
    135137// public
  • libcfa/src/strstream.hfa

    r92355883 r2a301ff  
    1010// Created On       : Thu Apr 22 22:20:59 2021
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Sun Oct 10 10:14:22 2021
    13 // Update Count     : 47
     12// Last Modified On : Fri Aug 18 10:41:14 2023
     13// Update Count     : 55
    1414//
    1515
     
    4747void sepSetCur$( ostrstream &, const char [] );
    4848bool getNL$( ostrstream & );
    49 void setNL$( ostrstream &, bool );
     49bool setNL$( ostrstream &, bool );
    5050bool getANL$( ostrstream & );
     51bool setANL$( ostrstream &, bool );
    5152bool getPrt$( ostrstream & );
    52 void setPrt$( ostrstream &, bool );
     53bool setPrt$( ostrstream &, bool );
    5354
    5455// public
    55 void sepOn( ostrstream & );
    56 void sepOff( ostrstream & );
    57 bool sepDisable( ostrstream & );
    58 bool sepEnable( ostrstream & );
    5956void nlOn( ostrstream & );
    6057void nlOff( ostrstream & );
    6158
     59void sep( ostrstream & );
     60void nosep( ostrstream & );
     61bool sepOn( ostrstream & );
     62bool sepOff( ostrstream & );
    6263const char * sepGet( ostrstream & );
    6364void sepSet( ostrstream &, const char [] );
     
    8788// private
    8889bool getANL$( istrstream & );
     90bool setANL$( istrstream &, bool );
    8991
    9092// public
  • libcfa/src/time.cfa

    r92355883 r2a301ff  
    1010// Created On       : Tue Mar 27 13:33:14 2018
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Tue Feb  4 08:24:18 2020
    13 // Update Count     : 70
     12// Last Modified On : Tue Jul 18 10:55:01 2023
     13// Update Count     : 71
    1414//
    1515
     
    4343                return os;
    4444        } // ?|?
    45 
    46         void ?|?( ostype & os, Duration dur ) with( dur ) {
    47                 (ostype &)(os | dur); ends( os );
    48         } // ?|?
     45        OSTYPE_VOID_IMPL( Duration )
    4946} // distribution
    5047
     
    155152                return os;
    156153        } // ?|?
    157 
    158         void ?|?( ostype & os, Time time ) with( time ) {
    159                 (ostype &)(os | time); ends( os );
    160         } // ?|?
     154        OSTYPE_VOID_IMPL( Time )
    161155} // distribution
    162156
  • libcfa/src/vec/vec.hfa

    r92355883 r2a301ff  
    7979}
    8080
    81 trait dottable(V, T) {
     81forall(V, T)
     82trait dottable {
    8283    T dot(V, V);
    8384};
  • libcfa/src/vec/vec2.hfa

    r92355883 r2a301ff  
    283283        return os | '<' | x | ',' | y | '>';
    284284    }
    285     void ?|?(ostype & os, vec2(T) v ) with (v) {
    286         (ostype &)(os | v); ends(os);
    287     }
     285        OSTYPE_VOID_IMPL( vec2(T) )
    288286}
  • libcfa/src/vec/vec3.hfa

    r92355883 r2a301ff  
    292292        return os | '<' | x | ',' | y | ',' | z | '>';
    293293    }
    294     void ?|?(ostype & os, vec3(T) v ) with (v) {
    295         (ostype &)(os | v); ends(os);
    296     }
     294        OSTYPE_VOID_IMPL( vec3(T) )
    297295}
  • libcfa/src/vec/vec4.hfa

    r92355883 r2a301ff  
    287287        return os | '<' | x | ',' | y | ',' | z | ',' | w | '>';
    288288    }
    289     void ?|?(ostype & os, vec4(T) v ) with (v) {
    290         (ostype &)(os | v); ends(os);
    291     }
     289        OSTYPE_VOID_IMPL( vec4(T) )
    292290}
    293291
  • 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.
    24// when using this, delete() is also virtual and will be called on the right address
    35// using free() directly on polymorphic types may result in unaligned memory deallocation
     
    810//     given struct A { inline virtual_dtor; } and struct B { inline virtual_dtor; }
    911//     struct C { inline A; inline B; } will result in undefined behaviour
    10 
    1112struct virtual_dtor {
    1213    void (*__virtual_dtor_ptr)(virtual_dtor &);
Note: See TracChangeset for help on using the changeset viewer.