Changes in / [a6c45c6:2d8a770]


Ignore:
Files:
21 edited

Legend:

Unmodified
Added
Removed
  • doc/LaTeXmacros/common.tex

    ra6c45c6 r2d8a770  
    1111%% Created On       : Sat Apr  9 10:06:17 2016
    1212%% Last Modified By : Peter A. Buhr
    13 %% Last Modified On : Sun Feb 14 15:52:46 2021
    14 %% Update Count     : 524
     13%% Last Modified On : Tue Apr 27 12:03:17 2021
     14%% Update Count     : 539
    1515%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    1616
     
    102102\renewcommand\subsubsection{\@startsection{subsubsection}{3}{\z@}{-2.5ex \@plus -1ex \@minus -.2ex}{1.0ex \@plus .2ex}{\normalfont\normalsize\bfseries}}
    103103\renewcommand\paragraph{\@startsection{paragraph}{4}{\z@}{-2.0ex \@plus -1ex \@minus -.2ex}{-1em}{\normalfont\normalsize\bfseries}}
     104\renewcommand\subparagraph{\@startsection{subparagraph}{4}{\z@}{-1.5ex \@plus -1ex \@minus -.2ex}{-1em}{\normalfont\normalsize\bfseries\itshape}}
    104105
    105106% index macros
     
    284285showlines=true,                                                 % show blank lines at end of code
    285286aboveskip=4pt,                                                  % spacing above/below code block
    286 belowskip=0pt,
     287belowskip=2pt,
    287288numberstyle=\footnotesize\sf,                   % numbering style
    288289% replace/adjust listing characters that look bad in sanserif
     
    297298\lstset{
    298299language=CFA,
    299 moredelim=**[is][\color{red}]{@}{@},    % red highlighting @...@
    300 %moredelim=**[is][\color{red}]{®}{®},   % red highlighting ®...® (registered trademark symbol) emacs: C-q M-.
     300%moredelim=**[is][\color{red}]{@}{@},   % red highlighting @...@
     301moredelim=**[is][\color{red}]{®}{®},    % red highlighting ®...® (registered trademark symbol) emacs: C-q M-.
    301302%moredelim=**[is][\color{blue}]{ß}{ß},  % blue highlighting ß...ß (sharp s symbol) emacs: C-q M-_
    302303%moredelim=**[is][\color{OliveGreen}]{¢}{¢}, % green highlighting ¢...¢ (cent symbol) emacs: C-q M-"
  • doc/user/user.tex

    ra6c45c6 r2d8a770  
    1111%% Created On       : Wed Apr  6 14:53:29 2016
    1212%% Last Modified By : Peter A. Buhr
    13 %% Last Modified On : Sun Apr 25 19:03:03 2021
    14 %% Update Count     : 4951
     13%% Last Modified On : Wed Apr 28 21:48:59 2021
     14%% Update Count     : 5051
    1515%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    1616
     
    33123312
    33133313\section{Tuples}
     3314\label{tuples}
    33143315
    33153316In C and \CFA, lists of elements appear in several contexts, such as the parameter list for a routine call.
     
    34203421
    34213422\subsection{Tuple Coercions}
     3423\label{tuple coercions}\label{coercions!tuple}
    34223424
    34233425There are four coercions that can be performed on tuples and tuple variables: closing, opening, flattening and structuring.
     
    34643466
    34653467\subsection{Mass Assignment}
     3468\label{mass assignment}\label{assignment!mass}
    34663469
    34673470\CFA permits assignment to several variables at once using mass assignment~\cite{CLU}.
     
    35043507
    35053508\subsection{Multiple Assignment}
     3509\label{multiple assignment}\label{assignment!multiple}
    35063510
    35073511\CFA also supports the assignment of several values at once, known as multiple assignment~\cite{CLU,Galletly96}.
     
    35453549
    35463550\subsection{Cascade Assignment}
     3551\index{cascade assignment}\index{assignment!cascade}
    35473552
    35483553As in C, \CFA mass and multiple assignments can be cascaded, producing cascade assignment.
     
    35643569\section{Stream I/O Library}
    35653570\label{s:StreamIOLibrary}
    3566 \index{input/output stream library}
    3567 \index{stream library}
     3571\index{input}\index{output}
     3572\index{stream library}\index{library!stream}
    35683573
    35693574The goal of \CFA stream input/output (I/O) is to simplify the common cases\index{I/O!common case}, while fully supporting polymorphism and user defined types in a consistent way.
    35703575Stream I/O can be implicitly or explicitly formatted.
    3571 Implicit formatting means \CFA selects the output or input format for values that match with the type of a variable.
     3576Implicit formatting means \CFA selects the output or input format for values that matches the variable's type.
    35723577Explicit formatting means additional information is specified to augment how an output or input of value is interpreted.
    3573 \CFA formatting is a cross between C ©printf© and \CC ©cout© manipulators, and Python implicit spacing and newline.
     3578\CFA formatting incorporates ideas from C ©printf©, \CC ©stream© manipulators, and Python implicit spacing and newline.
    35743579Specifically:
    35753580\begin{itemize}
     
    35843589Hence, it is common programming practice to toggle manipulators on and then back to the default to prevent downstream side-effects.
    35853590Without this programming style, errors occur when moving prints, as manipulator effects incorrectly flow into the new location.
    3586 (To guarantee no side-effects, manipulator values must be saved and restored across function calls.)
    3587 \item
    3588 \CFA has more sophisticated implicit spacing between values than Python, plus implicit newline at the end of a print.
     3591Furthermore, to guarantee no side-effects, manipulator values must be saved and restored across function calls.
     3592\item
     3593\CFA has more sophisticated implicit value spacing than Python, plus implicit newline at the end of a print.
    35893594\end{itemize}
     3595
     3596The standard polymorphic I/Os stream are ©stdin©/©sin© (input), ©stdout©/©sout© and ©stderr©/©serr© (output) (like C++ ©cin©/©cout©/©cerr©).
     3597Polymorphic streams ©exit© and ©abort© provide implicit program termination without and with generating a stack trace and core file.
     3598Stream ©exit© implicitly returns ©EXIT_FAILURE© to the shell.
     3599\begin{cfa}
     3600®exit®   | "x (" | x | ") negative value."; // terminate and return EXIT_FAILURE to shell
     3601®abort® | "x (" | x | ") negative value."; // terminate and generate stack trace and core file
     3602\end{cfa}
     3603Note, \CFA stream variables ©stdin©, ©stdout©, ©stderr©, ©exit©, and ©abort© overload C variables ©stdin©, ©stdout©, ©stderr©, and functions ©exit© and ©abort©, respectively.
    35903604The \CFA header file for the I/O library is \Indexc{fstream.hfa}.
     3605
     3606
     3607\subsection{Basic I/O}
    35913608
    35923609For implicit formatted output, the common case is printing a series of variables separated by whitespace.
     
    36013618\begin{cfa}
    36023619
    3603 cout << x ®<< " "® << y ®<< " "® << z << endl;
     3620cout  <<  x  ®<< " "®  <<  y  ®<< " "®  <<  z << endl;
    36043621\end{cfa}
    36053622&
     
    36533670\end{tabular}
    36543671\end{cquote}
    3655 Input and output use a uniform operator, ©|©, rather than separate operators, as in ©>>© and ©<<© for \CC.
     3672Input and output use a uniform operator, ©|©, rather than \CC's ©>>© and ©<<© input/output operators.
    36563673There is a weak similarity between the \CFA logical-or operator and the \Index{Shell pipe-operator} for moving data, where data flows in the correct direction for input but the opposite direction for output.
    36573674
     
    36983715\end{cquote}
    36993716
     3717\VRef[Figure]{f:CFACommand-LineProcessing} shows idiomatic \CFA command-line processing and copying an input file to an output file.
     3718Note, a stream variable may be copied because it is a reference to an underlying stream data-structures.
     3719All I/O errors are handles as exceptions, but end-of-file is not an exception as C programmers are use to explicitly checking for it.
     3720
     3721\begin{figure}
     3722\begin{cfa}
     3723#include ®<fstream.hfa>®
     3724
     3725int main( int argc, char * argv[] ) {
     3726        ®ifstream® in  = stdin;                                 $\C{// copy default files}$
     3727        ®ofstream® out = stdout;
     3728
     3729        try {
     3730                choose ( argc ) {
     3731                  case 2, 3:
     3732                        ®open®( in, argv[1] );                  $\C{// open input file first as output creates file}$
     3733                        if ( argc == 3 ) ®open®( out, argv[2] ); $\C{// do not create output unless input opens}$
     3734                  case 1: ;                                                     $\C{// use default files}$
     3735                  default:
     3736                        ®exit® | "Usage" | argv[0] | "[ input-file (default stdin) "
     3737                                   "[ output-file (default stdout) ] ]";
     3738                } // choose
     3739        } catch( ®Open_Failure® * ex; ex->istream == &in ) {
     3740                ®exit® | "Unable to open input file" | argv[1];
     3741        } catch( ®Open_Failure® * ex; ex->ostream == &out ) {
     3742                ®close®( in );                                          $\C{// optional}$
     3743                ®exit® | "Unable to open output file" | argv[2];
     3744        } // try
     3745
     3746        out | nlOff;                                                    $\C{// turn off auto newline}$
     3747        in | nlOn;                                                              $\C{// turn on reading newline}$
     3748        char ch;
     3749        for () {                                                                $\C{// read/write characters}$
     3750                in | ch;
     3751          if ( eof( in ) ) break;                               $\C{// eof ?}$
     3752                out | ch;
     3753        } // for
     3754} // main
     3755\end{cfa}
     3756\caption{\CFA Command-Line Processing}
     3757\label{f:CFACommand-LineProcessing}
     3758\end{figure}
     3759
     3760\VRef[Figure]{f:StreamFunctions} shows the stream operations.
     3761\begin{itemize}[topsep=4pt,itemsep=2pt,parsep=0pt]
     3762\item
     3763\Indexc{fail} tests the stream error-indicator, returning nonzero if it is set.
     3764\item
     3765\Indexc{clear} resets the stream error-indicator.
     3766\item
     3767\Indexc{flush} (©ofstream© only) causes any unwritten data for a stream to be written to the file.
     3768\item
     3769\Indexc{eof} (©ifstream© only) tests the end-of-file indicator for the stream pointed to by stream.
     3770Returns true if the end-of-file indicator is set, otherwise false.
     3771\item
     3772\Indexc{open} binds the file with ©name© to a stream accessed with ©mode© (see ©fopen©).
     3773\item
     3774\Indexc{close} flushes the stream and closes the file.
     3775\item
     3776\Indexc{write} (©ofstream© only) write ©size© bytes to the stream.
     3777The bytes are written lazily to file when internal buffers fill.
     3778Eager buffer writes are done with ©flush©
     3779\item
     3780\Indexc{read} (©ifstream© only) read ©size© bytes to the stream.
     3781\item
     3782\Indexc{ungetc} (©ifstream© only) pushes the character back to the input stream.
     3783Pushed-back characters returned by subsequent reads in the reverse order of pushing.
     3784\end{itemize}
     3785The constructor functions:
     3786\begin{itemize}[topsep=4pt,itemsep=2pt,parsep=0pt]
     3787\item
     3788create an unbound stream, which is subsequently bound to a file with ©open©.
     3789\item
     3790create a bound stream to the associated file with given ©mode©.
     3791\end{itemize}
     3792The destructor closes the stream.
     3793
     3794\begin{figure}
     3795\begin{cfa}
     3796// *********************************** ofstream ***********************************
     3797
     3798bool fail( ofstream & );$\indexc{fail}\index{ofstream@©ofstream©!©fail©}$
     3799void clear( ofstream & );$\indexc{clear}\index{ofstream@©ofstream©!©clear©}$
     3800int flush( ofstream & );$\indexc{flush}\index{ofstream@©ofstream©!©flush©}$
     3801void open( ofstream &, const char name[], const char mode[] = "w" );$\indexc{open}\index{ofstream@©ofstream©!©open©}$
     3802void close( ofstream & );$\indexc{close}\index{ofstream@©ofstream©!©close©}$
     3803ofstream & write( ofstream &, const char data[], size_t size );$\indexc{write}\index{ofstream@©ofstream©!©write©}$
     3804
     3805void ?{}( ofstream & );$\index{ofstream@©ofstream©!©?{}©}$
     3806void ?{}( ofstream &, const char name[], const char mode[] = "w" );
     3807void ^?{}( ofstream & );$\index{ofstream@©ofstream©!©^?{}©}$
     3808
     3809// *********************************** ifstream ***********************************
     3810
     3811bool fail( ifstream & is );$\indexc{fail}\index{ifstream@©ifstream©!©fail©}$
     3812void clear( ifstream & );$\indexc{clear}\index{ifstream@©ifstream©!©clear©}$
     3813bool eof( ifstream & is );$\indexc{eof}\index{ifstream@©ifstream©!©eof©}$
     3814void open( ifstream & is, const char name[], const char mode[] = "r" );$\indexc{open}\index{ifstream@©ifstream©!©open©}$
     3815void close( ifstream & is );$\indexc{close}\index{ifstream@©ifstream©!©close©}$
     3816ifstream & read( ifstream & is, char data[], size_t size );$\indexc{read}\index{ifstream@©ifstream©!©read©}$
     3817ifstream & ungetc( ifstream & is, char c );$\indexc{unget}\index{ifstream@©ifstream©!©unget©}$
     3818
     3819void ?{}( ifstream & is );$\index{ifstream@©ifstream©!©?{}©}$
     3820void ?{}( ifstream & is, const char name[], const char mode[] = "r" );
     3821void ^?{}( ifstream & is );$\index{ifstream@©ifstream©!©^?{}©}$
     3822\end{cfa}
     3823\caption{Stream Functions}
     3824\label{f:StreamFunctions}
     3825\end{figure}
    37003826
    37013827
     
    40304156sout | wd( 4, "ab" ) | wd( 3, "ab" ) | wd( 2, "ab" );
    40314157\end{cfa}
    4032 \begin{cfa}[showspaces=true,aboveskip=0pt,belowskip=0pt]
     4158\begin{cfa}[showspaces=true,aboveskip=0pt]
    40334159®  ®34 ® ®34 34
    40344160®  ®4.000000 ® ®4.000000 4.000000
     
    43784504\end{cfa}
    43794505
    4380 \Textbf{WARNING:} ©printf©\index{printf@©printf©}, ©scanf©\index{scanf@©scanf©} and their derivatives are unsafe when used with user-level threading, as in \CFA.
    4381 These stream routines use kernel-thread locking (©futex©\index{futex@©futex©}), which block kernel threads, to prevent interleaving of I/O.
    4382 However, the following simple example illustrates how a deadlock can occur (other complex scenarios are possible).
    4383 Assume a single kernel thread and two user-level threads calling ©printf©.
    4384 One user-level thread acquires the I/O lock and is time-sliced while performing ©printf©.
    4385 The other user-level thread then starts execution, calls ©printf©, and blocks the only kernel thread because it cannot acquire the I/O lock.
    4386 It does not help if the kernel lock is multiple acquisition, \ie, the lock owner can acquire it multiple times, because it then results in two user threads in the ©printf© critical section, corrupting the stream.
     4506
     4507\section{String Stream}
     4508
     4509All the stream formatting capabilities are available to format text to/from a C string rather than to a stream file.
     4510\VRef[Figure]{f:StringStreamProcessing} shows writing (output) and reading (input) from a C string.
     4511\begin{figure}
     4512\begin{cfa}
     4513#include <fstream.hfa>
     4514#include <strstream.hfa>
     4515
     4516int main() {
     4517        enum { size = 256 };
     4518        char buf[size]; $\C{// output buffer}$
     4519        ®ostrstream osstr = { buf, size };® $\C{// bind output buffer/size}$
     4520        int i = 3, j = 5, k = 7;
     4521        double x = 12345678.9, y = 98765.4321e-11;
     4522
     4523        osstr | i | hex(j) | wd(10, k) | sci(x) | unit(eng(y)); $\C{// same lines of output}$
     4524        write( osstr );
     4525        printf( "%s", buf );
     4526        sout | i | hex(j) | wd(10, k) | sci(x) | unit(eng(y));
     4527
     4528        char buf2[] = "12 14 15 3.5 7e4"; $\C{// input buffer}$
     4529        ®istrstream isstr = { buf2 };®
     4530        isstr | i | j | k | x | y;
     4531        sout | i | j | k | x | y;
     4532}
     4533\end{cfa}
     4534\caption{String Stream Processing}
     4535\label{f:StringStreamProcessing}
     4536\end{figure}
     4537
     4538\VRef[Figure]{f:StringStreamFunctions} shows the string stream operations.
     4539\begin{itemize}[topsep=4pt,itemsep=2pt,parsep=0pt]
     4540\item
     4541\Indexc{write} (©ostrstream© only) writes all the buffered characters to the specified stream (©stdout© default).
     4542\end{itemize}
     4543The constructor functions:
     4544\begin{itemize}[topsep=4pt,itemsep=2pt,parsep=0pt]
     4545\item
     4546create a bound stream to a write buffer (©ostrstream©) of ©size© or a read buffer (©istrstream©) containing a C string terminated with ©'\0'©.
     4547\end{itemize}
     4548
     4549\begin{figure}
     4550\begin{cfa}
     4551// *********************************** ostrstream ***********************************
     4552
     4553ostrstream & write( ostrstream & os, FILE * stream = stdout );
     4554
     4555void ?{}( ostrstream &, char buf[], size_t size );
     4556
     4557// *********************************** istrstream ***********************************
     4558
     4559void ?{}( istrstream & is, char buf[] );
     4560\end{cfa}
     4561\caption{String Stream Functions}
     4562\label{f:StringStreamFunctions}
     4563\end{figure}
    43874564
    43884565
     
    81118288\begin{cquote}
    81128289\begin{tabular}{@{}l@{\hspace{\parindentlnth}}|@{\hspace{\parindentlnth}}l@{}}
    8113 \multicolumn{1}{@{}c|@{\hspace{\parindentlnth}}}{\textbf{\CFA}} & \multicolumn{1}{@{\hspace{\parindentlnth}}c}{\textbf{C}@{}}   \\
     8290\multicolumn{1}{@{}c|@{\hspace{\parindentlnth}}}{\textbf{\CFA}} & \multicolumn{1}{@{\hspace{\parindentlnth}}c@{}}{\textbf{C}}   \\
    81148291\hline
    81158292\begin{cfa}
    8116 #include <gmp>$\indexc{gmp}$
     8293#include <gmp.hfa>$\indexc{gmp}$
    81178294int main( void ) {
    81188295        sout | "Factorial Numbers";
  • libcfa/src/concurrency/clib/cfathread.cfa

    ra6c45c6 r2d8a770  
    243243        // Mutex
    244244        struct cfathread_mutex {
    245                 single_acquisition_lock impl;
     245                fast_lock impl;
    246246        };
    247247        int cfathread_mutex_init(cfathread_mutex_t *restrict mut, const cfathread_mutexattr_t *restrict) __attribute__((nonnull (1))) { *mut = new(); return 0; }
     
    258258        // Condition
    259259        struct cfathread_condition {
    260                 condition_variable(single_acquisition_lock) impl;
     260                condition_variable(fast_lock) impl;
    261261        };
    262262        int cfathread_cond_init(cfathread_cond_t *restrict cond, const cfathread_condattr_t *restrict) __attribute__((nonnull (1))) { *cond = new(); return 0; }
  • libcfa/src/concurrency/invoke.h

    ra6c45c6 r2d8a770  
    148148                struct $thread * prev;
    149149                volatile unsigned long long ts;
     150                unsigned preferred;
    150151        };
    151152
     
    199200                } node;
    200201
     202                struct processor * last_proc;
     203
    201204                #if defined( __CFA_WITH_VERIFY__ )
    202205                        void * canary;
  • libcfa/src/concurrency/io.cfa

    ra6c45c6 r2d8a770  
    4040        #include "kernel.hfa"
    4141        #include "kernel/fwd.hfa"
     42        #include "kernel_private.hfa"
    4243        #include "io/types.hfa"
    4344
     
    8990        static inline unsigned __flush( struct $io_context & );
    9091        static inline __u32 __release_sqes( struct $io_context & );
     92        extern void __kernel_unpark( $thread * thrd );
    9193
    9294        bool __cfa_io_drain( processor * proc ) {
    9395                /* paranoid */ verify( ! __preemption_enabled() );
     96                /* paranoid */ verify( ready_schedule_islocked() );
    9497                /* paranoid */ verify( proc );
    9598                /* paranoid */ verify( proc->io.ctx );
     
    115118                        __cfadbg_print_safe( io, "Kernel I/O : Syscall completed : cqe %p, result %d for %p\n", &cqe, cqe.res, future );
    116119
    117                         fulfil( *future, cqe.res );
     120                        __kernel_unpark( fulfil( *future, cqe.res, false ) );
    118121                }
    119122
     
    124127                __atomic_store_n( ctx->cq.head, head + count, __ATOMIC_SEQ_CST );
    125128
     129                /* paranoid */ verify( ready_schedule_islocked() );
    126130                /* paranoid */ verify( ! __preemption_enabled() );
    127131
  • libcfa/src/concurrency/kernel.cfa

    ra6c45c6 r2d8a770  
    3434#include "invoke.h"
    3535
     36#if !defined(__CFA_NO_STATISTICS__)
     37        #define __STATS( ...) __VA_ARGS__
     38#else
     39        #define __STATS( ...)
     40#endif
    3641
    3742//-----------------------------------------------------------------------------
     
    166171                preemption_scope scope = { this };
    167172
    168                 #if !defined(__CFA_NO_STATISTICS__)
    169                         unsigned long long last_tally = rdtscl();
    170                 #endif
     173                __STATS( unsigned long long last_tally = rdtscl(); )
    171174
    172175                // if we need to run some special setup, now is the time to do it.
     
    266269                                __cfa_io_flush( this );
    267270                        }
     271
     272                //      SEARCH: {
     273                //              /* paranoid */ verify( ! __preemption_enabled() );
     274                //              /* paranoid */ verify( kernelTLS().this_proc_id );
     275
     276                //              // First, lock the scheduler since we are searching for a thread
     277
     278                //              // Try to get the next thread
     279                //              ready_schedule_lock();
     280                //              readyThread = pop_fast( this->cltr );
     281                //              ready_schedule_unlock();
     282                //              if(readyThread) {  break SEARCH; }
     283
     284                //              // If we can't find a thread, might as well flush any outstanding I/O
     285                //              if(this->io.pending) { __cfa_io_flush( this ); }
     286
     287                //              // Spin a little on I/O, just in case
     288                //              for(25) {
     289                //                      __maybe_io_drain( this );
     290                //                      ready_schedule_lock();
     291                //                      readyThread = pop_fast( this->cltr );
     292                //                      ready_schedule_unlock();
     293                //                      if(readyThread) {  break SEARCH; }
     294                //              }
     295
     296                //              // no luck, try stealing a few times
     297                //              for(25) {
     298                //                      if( __maybe_io_drain( this ) ) {
     299                //                              ready_schedule_lock();
     300                //                              readyThread = pop_fast( this->cltr );
     301                //                      } else {
     302                //                              ready_schedule_lock();
     303                //                              readyThread = pop_slow( this->cltr );
     304                //                      }
     305                //                      ready_schedule_unlock();
     306                //                      if(readyThread) {  break SEARCH; }
     307                //              }
     308
     309                //              // still no luck, search for a thread
     310                //              ready_schedule_lock();
     311                //              readyThread = pop_search( this->cltr );
     312                //              ready_schedule_unlock();
     313                //              if(readyThread) { break SEARCH; }
     314
     315                //              // Don't block if we are done
     316                //              if( __atomic_load_n(&this->do_terminate, __ATOMIC_SEQ_CST) ) break MAIN_LOOP;
     317
     318                //              __STATS( __tls_stats()->ready.sleep.halts++; )
     319
     320                //              // Push self to idle stack
     321                //              mark_idle(this->cltr->procs, * this);
     322
     323                //              // Confirm the ready-queue is empty
     324                //              __maybe_io_drain( this );
     325                //              ready_schedule_lock();
     326                //              readyThread = pop_search( this->cltr );
     327                //              ready_schedule_unlock();
     328
     329                //              if( readyThread ) {
     330                //                      // A thread was found, cancel the halt
     331                //                      mark_awake(this->cltr->procs, * this);
     332
     333                //                      __STATS( __tls_stats()->ready.sleep.cancels++; )
     334
     335                //                      // continue the main loop
     336                //                      break SEARCH;
     337                //              }
     338
     339                //              __STATS( if(this->print_halts) __cfaabi_bits_print_safe( STDOUT_FILENO, "PH:%d - %lld 0\n", this->id, rdtscl()); )
     340                //              __cfadbg_print_safe(runtime_core, "Kernel : core %p waiting on eventfd %d\n", this, this->idle);
     341
     342                //              // __disable_interrupts_hard();
     343                //              eventfd_t val;
     344                //              eventfd_read( this->idle, &val );
     345                //              // __enable_interrupts_hard();
     346
     347                //              __STATS( if(this->print_halts) __cfaabi_bits_print_safe( STDOUT_FILENO, "PH:%d - %lld 1\n", this->id, rdtscl()); )
     348
     349                //              // We were woken up, remove self from idle
     350                //              mark_awake(this->cltr->procs, * this);
     351
     352                //              // DON'T just proceed, start looking again
     353                //              continue MAIN_LOOP;
     354                //      }
     355
     356                // RUN_THREAD:
     357                //      /* paranoid */ verify( kernelTLS().this_proc_id );
     358                //      /* paranoid */ verify( ! __preemption_enabled() );
     359                //      /* paranoid */ verify( readyThread );
     360
     361                //      // Reset io dirty bit
     362                //      this->io.dirty = false;
     363
     364                //      // We found a thread run it
     365                //      __run_thread(this, readyThread);
     366
     367                //      // Are we done?
     368                //      if( __atomic_load_n(&this->do_terminate, __ATOMIC_SEQ_CST) ) break MAIN_LOOP;
     369
     370                //      #if !defined(__CFA_NO_STATISTICS__)
     371                //              unsigned long long curr = rdtscl();
     372                //              if(curr > (last_tally + 500000000)) {
     373                //                      __tally_stats(this->cltr->stats, __cfaabi_tls.this_stats);
     374                //                      last_tally = curr;
     375                //              }
     376                //      #endif
     377
     378                //      if(this->io.pending && !this->io.dirty) {
     379                //              __cfa_io_flush( this );
     380                //      }
     381
     382                //      // Check if there is pending io
     383                //      __maybe_io_drain( this );
    268384                }
    269385
     
    402518        $thread * thrd_src = kernelTLS().this_thread;
    403519
    404         #if !defined(__CFA_NO_STATISTICS__)
    405                 struct processor * last_proc = kernelTLS().this_processor;
    406         #endif
     520        __STATS( thrd_src->last_proc = kernelTLS().this_processor; )
    407521
    408522        // Run the thread on this processor
     
    423537
    424538        #if !defined(__CFA_NO_STATISTICS__)
    425                 if(last_proc != kernelTLS().this_processor) {
     539                /* paranoid */ verify( thrd_src->last_proc != 0p );
     540                if(thrd_src->last_proc != kernelTLS().this_processor) {
    426541                        __tls_stats()->ready.threads.migration++;
    427542                }
     
    436551// Scheduler routines
    437552// KERNEL ONLY
    438 void __schedule_thread( $thread * thrd ) {
     553static void __schedule_thread( $thread * thrd ) {
    439554        /* paranoid */ verify( ! __preemption_enabled() );
    440555        /* paranoid */ verify( kernelTLS().this_proc_id );
     
    457572        // Dereference the thread now because once we push it, there is not guaranteed it's still valid.
    458573        struct cluster * cl = thrd->curr_cluster;
     574        __STATS(bool outside = thrd->last_proc && thrd->last_proc != kernelTLS().this_processor; )
    459575
    460576        // push the thread to the cluster ready-queue
     
    470586                if( kernelTLS().this_stats ) {
    471587                        __tls_stats()->ready.threads.threads++;
     588                        if(outside) {
     589                                __tls_stats()->ready.threads.extunpark++;
     590                        }
    472591                        __push_stat( __tls_stats(), __tls_stats()->ready.threads.threads, false, "Processor", kernelTLS().this_processor );
    473592                }
    474593                else {
    475594                        __atomic_fetch_add(&cl->stats->ready.threads.threads, 1, __ATOMIC_RELAXED);
     595                        __atomic_fetch_add(&cl->stats->ready.threads.extunpark, 1, __ATOMIC_RELAXED);
    476596                        __push_stat( cl->stats, cl->stats->ready.threads.threads, true, "Cluster", cl );
    477597                }
     
    508628
    509629        ready_schedule_lock();
    510                 $thread * thrd = pop_slow( this );
     630                $thread * thrd;
     631                for(25) {
     632                        thrd = pop_slow( this );
     633                        if(thrd) goto RET;
     634                }
     635                thrd = pop_search( this );
     636
     637                RET:
    511638        ready_schedule_unlock();
    512639
     
    532659}
    533660
     661void __kernel_unpark( $thread * thrd ) {
     662        /* paranoid */ verify( ! __preemption_enabled() );
     663        /* paranoid */ verify( ready_schedule_islocked());
     664
     665        if( !thrd ) return;
     666
     667        if(__must_unpark(thrd)) {
     668                // Wake lost the race,
     669                __schedule_thread( thrd );
     670        }
     671
     672        /* paranoid */ verify( ready_schedule_islocked());
     673        /* paranoid */ verify( ! __preemption_enabled() );
     674}
     675
    534676void unpark( $thread * thrd ) {
    535677        if( !thrd ) return;
     
    744886
    745887static inline bool __maybe_io_drain( processor * proc ) {
     888        bool ret = false;
    746889        #if defined(CFA_HAVE_LINUX_IO_URING_H)
    747890                __cfadbg_print_safe(runtime_core, "Kernel : core %p checking io for ring %d\n", proc, proc->io.ctx->fd);
     
    752895                unsigned tail = *ctx->cq.tail;
    753896                if(head == tail) return false;
    754                 return __cfa_io_drain( proc );
     897                ready_schedule_lock();
     898                ret = __cfa_io_drain( proc );
     899                ready_schedule_unlock();
    755900        #endif
     901        return ret;
    756902}
    757903
  • libcfa/src/concurrency/kernel/startup.cfa

    ra6c45c6 r2d8a770  
    447447        link.next = 0p;
    448448        link.prev = 0p;
     449        link.preferred = -1u;
     450        last_proc = 0p;
    449451        #if defined( __CFA_WITH_VERIFY__ )
    450452                canary = 0x0D15EA5E0D15EA5Ep;
  • libcfa/src/concurrency/kernel_private.hfa

    ra6c45c6 r2d8a770  
    284284
    285285//-----------------------------------------------------------------------
    286 // pop thread from the ready queue of a cluster
     286// pop thread from the local queues of a cluster
    287287// returns 0p if empty
    288288// May return 0p spuriously
     
    290290
    291291//-----------------------------------------------------------------------
    292 // pop thread from the ready queue of a cluster
     292// pop thread from any ready queue of a cluster
     293// returns 0p if empty
     294// May return 0p spuriously
     295__attribute__((hot)) struct $thread * pop_slow(struct cluster * cltr);
     296
     297//-----------------------------------------------------------------------
     298// search all ready queues of a cluster for any thread
    293299// returns 0p if empty
    294300// guaranteed to find any threads added before this call
    295 __attribute__((hot)) struct $thread * pop_slow(struct cluster * cltr);
     301__attribute__((hot)) struct $thread * pop_search(struct cluster * cltr);
    296302
    297303//-----------------------------------------------------------------------
  • libcfa/src/concurrency/ready_queue.cfa

    ra6c45c6 r2d8a770  
    344344        }
    345345
    346         __attribute__((hot)) struct $thread * pop_slow(struct cluster * cltr) {
     346        __attribute__((hot)) struct $thread * pop_slow(struct cluster * cltr) { return pop_fast(cltr); }
     347        __attribute__((hot)) struct $thread * pop_search(struct cluster * cltr) {
    347348                return search(cltr);
    348349        }
     
    436437
    437438        __attribute__((hot)) struct $thread * pop_slow(struct cluster * cltr) with (cltr->ready_queue) {
    438                 for(25) {
    439                         unsigned i = __tls_rand() % lanes.count;
    440                         $thread * t = try_pop(cltr, i __STATS(, __tls_stats()->ready.pop.steal));
    441                         if(t) return t;
    442                 }
    443 
     439                unsigned i = __tls_rand() % lanes.count;
     440                return try_pop(cltr, i __STATS(, __tls_stats()->ready.pop.steal));
     441        }
     442
     443        __attribute__((hot)) struct $thread * pop_search(struct cluster * cltr) with (cltr->ready_queue) {
    444444                return search(cltr);
    445445        }
  • libcfa/src/concurrency/stats.cfa

    ra6c45c6 r2d8a770  
    3838                stats->ready.pop.search.espec   = 0;
    3939                stats->ready.threads.migration = 0;
     40                stats->ready.threads.extunpark = 0;
    4041                stats->ready.threads.threads   = 0;
    4142                stats->ready.sleep.halts   = 0;
     
    9596                __atomic_fetch_add( &cltr->ready.pop.search.espec  , proc->ready.pop.search.espec  , __ATOMIC_SEQ_CST ); proc->ready.pop.search.espec   = 0;
    9697                __atomic_fetch_add( &cltr->ready.threads.migration , proc->ready.threads.migration , __ATOMIC_SEQ_CST ); proc->ready.threads.migration  = 0;
     98                __atomic_fetch_add( &cltr->ready.threads.extunpark , proc->ready.threads.extunpark , __ATOMIC_SEQ_CST ); proc->ready.threads.extunpark  = 0;
    9799                __atomic_fetch_add( &cltr->ready.threads.threads   , proc->ready.threads.threads   , __ATOMIC_SEQ_CST ); proc->ready.threads.threads    = 0;
    98100                __atomic_fetch_add( &cltr->ready.sleep.halts       , proc->ready.sleep.halts       , __ATOMIC_SEQ_CST ); proc->ready.sleep.halts        = 0;
     
    124126
    125127                char buf[1024];
    126                 strstream sstr = { buf, 1024 };
     128                ostrstream sstr = { buf, 1024 };
    127129
    128130                if( flags & CFA_STATS_READY_Q ) {
     
    132134                        uint64_t totalR = ready.pop.local.success + ready.pop.help.success + ready.pop.steal.success + ready.pop.search.success;
    133135                        uint64_t totalS = ready.push.local.success + ready.push.share.success + ready.push.extrn.success;
    134                         sstr | "- totals   : " | eng3(totalR) | "run," | eng3(totalS) | "schd (" | eng3(ready.push.extrn.success) | "ext," | eng3(ready.threads.migration) | "mig)";
     136                        sstr | "- totals   : " | eng3(totalR) | "run," | eng3(totalS) | "schd (" | eng3(ready.push.extrn.success) | "ext," | eng3(ready.threads.migration) | "mig," | eng3(ready.threads.extunpark) | " eupk)";
    135137
    136138                        double push_len = ((double)ready.push.local.attempt + ready.push.share.attempt + ready.push.extrn.attempt) / totalS;
  • libcfa/src/concurrency/stats.hfa

    ra6c45c6 r2d8a770  
    7070                struct {
    7171                        volatile uint64_t migration;
     72                        volatile uint64_t extunpark;
    7273                        volatile  int64_t threads; // number of threads in the system, includes only local change
    7374                } threads;
  • libcfa/src/concurrency/thread.cfa

    ra6c45c6 r2d8a770  
    3939        link.next = 0p;
    4040        link.prev = 0p;
     41        link.preferred = -1u;
     42        last_proc = 0p;
    4143        #if defined( __CFA_WITH_VERIFY__ )
    4244                canary = 0x0D15EA5E0D15EA5Ep;
  • libcfa/src/fstream.cfa

    ra6c45c6 r2d8a770  
    1010// Created On       : Wed May 27 17:56:53 2015
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Sat Apr 24 09:05:16 2021
    13 // Update Count     : 426
    14 //
    15 
    16 #include "fstream.hfa"
     12// Last Modified On : Wed Apr 28 20:37:53 2021
     13// Update Count     : 445
     14//
     15
     16#include "fstream.hfa"                                                                  // also includes iostream.hfa
    1717
    1818#include <stdio.h>                                                                              // vfprintf, vfscanf
     
    114114} // fail
    115115
     116void clear( ofstream & os ) {
     117        clearerr( (FILE *)(os.file$) );
     118} // clear
     119
    116120int flush( ofstream & os ) {
    117121        return fflush( (FILE *)(os.file$) );
     
    196200ofstream & abort = abortFile;
    197201
     202ofstream & nl( ofstream & os ) {
     203        nl$( os );                                                                                      // call basic_ostream nl
     204        flush( os );
     205        return os;
     206        // (ofstream &)(os | '\n');
     207        // setPrt$( os, false );                                                        // turn off
     208        // setNL$( os, true );
     209        // flush( os );
     210        // return sepOff( os );                                                 // prepare for next line
     211} // nl
     212
    198213
    199214// *********************************** ifstream ***********************************
     
    230245} // fail
    231246
     247void clear( ifstream & is ) {
     248        clearerr( (FILE *)(is.file$) );
     249} // clear
     250
    232251void ends( ifstream & is ) {
    233252        if ( is.acquired$ ) { is.acquired$ = false; release( is ); }
    234253} // ends
    235254
    236 int eof( ifstream & is ) {
     255bool eof( ifstream & is ) {
    237256        return feof( (FILE *)(is.file$) );
    238257} // eof
     
    263282} // close
    264283
    265 ifstream & read( ifstream & is, char * data, size_t size ) {
     284ifstream & read( ifstream & is, char data[], size_t size ) {
    266285        if ( fail( is ) ) {
    267286                abort | IO_MSG "attempt read I/O on failed stream";
  • libcfa/src/fstream.hfa

    ra6c45c6 r2d8a770  
    1010// Created On       : Wed May 27 17:56:53 2015
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Sat Apr 24 09:04:03 2021
    13 // Update Count     : 219
     12// Last Modified On : Wed Apr 28 20:37:57 2021
     13// Update Count     : 230
    1414//
    1515
     
    7070
    7171bool fail( ofstream & );
     72void clear( ofstream & );
    7273int flush( ofstream & );
    73 void open( ofstream &, const char name[], const char mode[] );
     74void open( ofstream &, const char name[], const char mode[] ); // FIX ME: use default = "w"
    7475void open( ofstream &, const char name[] );
    7576void close( ofstream & );
     
    8687
    8788void ?{}( ofstream & );
    88 void ?{}( ofstream &, const char name[], const char mode[] );
     89void ?{}( ofstream &, const char name[], const char mode[] ); // FIX ME: use default = "w"
    8990void ?{}( ofstream &, const char name[] );
    9091void ^?{}( ofstream & );
     92
     93// private
     94static inline ofstream & nl$( ofstream & os ) { return nl( os ); } // remember basic_ostream nl
     95// public
     96ofstream & nl( ofstream & os );                                                 // override basic_ostream nl
    9197
    9298extern ofstream & sout, & stdout, & serr, & stderr;             // aliases
     
    111117bool getANL( ifstream & );
    112118void ends( ifstream & );
     119int fmt( ifstream &, const char format[], ... ) __attribute__(( format(scanf, 2, 3) ));
     120
    113121bool fail( ifstream & is );
    114 int eof( ifstream & is );
    115 void open( ifstream & is, const char name[], const char mode[] );
     122void clear( ifstream & );
     123bool eof( ifstream & is );
     124void open( ifstream & is, const char name[], const char mode[] ); // FIX ME: use default = "r"
    116125void open( ifstream & is, const char name[] );
    117126void close( ifstream & is );
    118 ifstream & read( ifstream & is, char * data, size_t size );
     127ifstream & read( ifstream & is, char data[], size_t size );
    119128ifstream & ungetc( ifstream & is, char c );
    120 int fmt( ifstream &, const char format[], ... ) __attribute__(( format(scanf, 2, 3) ));
     129
    121130void acquire( ifstream & is );
    122131void release( ifstream & is );
     
    129138
    130139void ?{}( ifstream & is );
    131 void ?{}( ifstream & is, const char name[], const char mode[] );
     140void ?{}( ifstream & is, const char name[], const char mode[] ); // FIX ME: use default = "r"
    132141void ?{}( ifstream & is, const char name[] );
    133142void ^?{}( ifstream & is );
  • libcfa/src/iostream.cfa

    ra6c45c6 r2d8a770  
    1010// Created On       : Wed May 27 17:56:53 2015
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Sat Apr 24 10:03:54 2021
    13 // Update Count     : 1329
     12// Last Modified On : Tue Apr 27 18:01:03 2021
     13// Update Count     : 1330
    1414//
    1515
     
    145145        } // ?|?
    146146
    147 #if defined( __SIZEOF_INT128__ )
     147        #if defined( __SIZEOF_INT128__ )
    148148        //      UINT64_MAX 18_446_744_073_709_551_615_ULL
    149149        #define P10_UINT64 10_000_000_000_000_000_000_ULL       // 19 zeroes
    150150
    151151        static inline void base10_128( ostype & os, unsigned int128 val ) {
    152 #if defined(__GNUC__) && __GNUC_PREREQ(7,0)                             // gcc version >= 7
     152                #if defined(__GNUC__) && __GNUC_PREREQ(7,0)             // gcc version >= 7
    153153                if ( val > P10_UINT64 ) {
    154 #else
     154                #else
    155155                if ( (uint64_t)(val >> 64) != 0 || (uint64_t)val > P10_UINT64 ) { // patch gcc 5 & 6 -O3 bug
    156 #endif // __GNUC_PREREQ(7,0)
     156                #endif // __GNUC_PREREQ(7,0)
    157157                        base10_128( os, val / P10_UINT64 );                     // recursive
    158158                        fmt( os, "%.19lu", (uint64_t)(val % P10_UINT64) );
     
    187187                (ostype &)(os | ullli); ends( os );
    188188        } // ?|?
    189 #endif // __SIZEOF_INT128__
     189        #endif // __SIZEOF_INT128__
    190190
    191191        #define PrintWithDP( os, format, val, ... ) \
     
    361361                setPrt$( os, false );                                                   // turn off
    362362                setNL$( os, true );
    363                 flush( os );
    364363                return sepOff( os );                                                    // prepare for next line
    365364        } // nl
     
    808807
    809808
    810 forall( istype & | istream( istype ) ) {
     809forall( istype & | basic_istream( istype ) ) {
    811810        istype & ?|?( istype & is, bool & b ) {
    812811                char val[6];
     
    918917        } // ?|?
    919918
    920 #if defined( __SIZEOF_INT128__ )
     919        #if defined( __SIZEOF_INT128__ )
    921920        istype & ?|?( istype & is, int128 & llli ) {
    922921                return (istype &)(is | (unsigned int128 &)llli);
     
    944943                (istype &)(is | ullli); ends( is );
    945944        } // ?|?
    946 #endif // __SIZEOF_INT128__
     945        #endif // __SIZEOF_INT128__
    947946
    948947        istype & ?|?( istype & is, float & f ) {
     
    10351034                return is;
    10361035        } // nlOff
    1037 
     1036} // distribution
     1037
     1038forall( istype & | istream( istype ) ) {
    10381039        istype & acquire( istype & is ) {
    10391040                acquire( is );                                                                  // call void returning
     
    10441045// *********************************** manipulators ***********************************
    10451046
    1046 forall( istype & | istream( istype ) ) {
     1047forall( istype & | basic_istream( istype ) ) {
    10471048        istype & ?|?( istype & is, _Istream_Cstr f ) {
    10481049                // skip xxx
     
    10921093
    10931094#define InputFMTImpl( T, CODE ) \
    1094 forall( istype & | istream( istype ) ) { \
     1095forall( istype & | basic_istream( istype ) ) { \
    10951096        istype & ?|?( istype & is, _Istream_Manip(T) f ) { \
    10961097                enum { size = 16 }; \
     
    11251126InputFMTImpl( long double, "Lf" )
    11261127
    1127 forall( istype & | istream( istype ) ) {
     1128forall( istype & | basic_istream( istype ) ) {
    11281129        istype & ?|?( istype & is, _Istream_Manip(float _Complex) fc ) {
    11291130                float re, im;
  • libcfa/src/iostream.hfa

    ra6c45c6 r2d8a770  
    1010// Created On       : Wed May 27 17:56:53 2015
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Sun Apr 25 11:22:03 2021
    13 // Update Count     : 397
     12// Last Modified On : Wed Apr 28 20:37:56 2021
     13// Update Count     : 401
    1414//
    1515
     
    4949        void ends( ostype & );                                                          // end of output statement
    5050        int fmt( ostype &, const char format[], ... ) __attribute__(( format(printf, 2, 3) ));
    51         int flush( ostype & );
    5251}; // basic_ostream
    5352       
    5453trait ostream( ostype & | basic_ostream( ostype ) ) {
    5554        bool fail( ostype & );                                                          // operation failed?
     55        void clear( ostype & );
     56        int flush( ostype & );
    5657        void open( ostype &, const char name[], const char mode[] );
    5758        void close( ostype & );
     
    9798        ostype & ?|?( ostype &, unsigned long long int );
    9899        void ?|?( ostype &, unsigned long long int );
    99 #if defined( __SIZEOF_INT128__ )
     100        #if defined( __SIZEOF_INT128__ )
    100101        ostype & ?|?( ostype &, int128 );
    101102        void ?|?( ostype &, int128 );
    102103        ostype & ?|?( ostype &, unsigned int128 );
    103104        void ?|?( ostype &, unsigned int128 );
    104 #endif // __SIZEOF_INT128__
     105        #endif // __SIZEOF_INT128__
    105106
    106107        ostype & ?|?( ostype &, float );
     
    121122        void ?|?( ostype &, const char [] );
    122123        // ostype & ?|?( ostype &, const char16_t * );
    123 #if ! ( __ARM_ARCH_ISA_ARM == 1 && __ARM_32BIT_STATE == 1 ) // char32_t == wchar_t => ambiguous
     124        #if ! ( __ARM_ARCH_ISA_ARM == 1 && __ARM_32BIT_STATE == 1 ) // char32_t == wchar_t => ambiguous
    124125        // ostype & ?|?( ostype &, const char32_t * );
    125 #endif // ! ( __ARM_ARCH_ISA_ARM == 1 && __ARM_32BIT_STATE == 1 )
     126        #endif // ! ( __ARM_ARCH_ISA_ARM == 1 && __ARM_32BIT_STATE == 1 )
    126127        // ostype & ?|?( ostype &, const wchar_t * );
    127128        ostype & ?|?( ostype &, const void * );
     
    294295
    295296
    296 trait istream( istype & ) {
     297trait basic_istream( istype & ) {
     298        bool getANL( istype & );                                                        // get scan newline (on/off)
    297299        void nlOn( istype & );                                                          // read newline
    298300        void nlOff( istype & );                                                         // scan newline
    299         bool getANL( istype & );                                                        // get scan newline (on/off)
    300301
    301302        void ends( istype & os );                                                       // end of output statement
     303        int fmt( istype &, const char format[], ... ) __attribute__(( format(scanf, 2, 3) ));
     304        istype & ungetc( istype &, char );
     305        bool eof( istype & );
     306}; // basic_istream
     307
     308trait istream( istype & | basic_istream( istype ) ) {
    302309        bool fail( istype & );
    303         int eof( istype & );
     310        void clear( istype & );
    304311        void open( istype & is, const char name[] );
    305312        void close( istype & is );
    306         istype & read( istype &, char *, size_t );
    307         istype & ungetc( istype &, char );
    308         int fmt( istype &, const char format[], ... ) __attribute__(( format(scanf, 2, 3) ));
    309         void acquire( istype & );
     313        istype & read( istype &, char [], size_t );
     314        void acquire( istype & );                                                       // concurrent access
    310315}; // istream
    311316
     
    314319}; // readable
    315320
    316 forall( istype & | istream( istype ) ) {
     321forall( istype & | basic_istream( istype ) ) {
    317322        istype & ?|?( istype &, bool & );
    318323        void ?|?( istype &, bool & );
     
    341346        istype & ?|?( istype &, unsigned long long int & );
    342347        void ?|?( istype &, unsigned long long int & );
    343 #if defined( __SIZEOF_INT128__ )
     348        #if defined( __SIZEOF_INT128__ )
    344349        istype & ?|?( istype &, int128 & );
    345350        void ?|?( istype &, int128 & );
    346351        istype & ?|?( istype &, unsigned int128 & );
    347352        void ?|?( istype &, unsigned int128 & );
    348 #endif // __SIZEOF_INT128__
     353        #endif // __SIZEOF_INT128__
    349354
    350355        istype & ?|?( istype &, float & );
     
    372377        istype & nlOn( istype & );
    373378        istype & nlOff( istype & );
     379} // distribution
     380
     381forall( istype & | istream( istype ) ) {
    374382        istype & acquire( istype & );
    375383} // distribution
     
    402410        _Istream_Cstr & wdi( unsigned int w, _Istream_Cstr & fmt ) { fmt.wd = w; return fmt; }
    403411} // distribution
    404 forall( istype & | istream( istype ) ) {
     412forall( istype & | basic_istream( istype ) ) {
    405413        istype & ?|?( istype & is, _Istream_Cstr f );
    406414        void ?|?( istype & is, _Istream_Cstr f );
     
    415423        _Istream_Char & ignore( _Istream_Char & fmt ) { fmt.ignore = true; return fmt; }
    416424} // distribution
    417 forall( istype & | istream( istype ) ) {
     425forall( istype & | basic_istream( istype ) ) {
    418426        istype & ?|?( istype & is, _Istream_Char f );
    419427        void ?|?( istype & is, _Istream_Char f );
     
    434442        _Istream_Manip(T) & wdi( unsigned int w, _Istream_Manip(T) & fmt ) { fmt.wd = w; return fmt; } \
    435443} /* distribution */ \
    436 forall( istype & | istream( istype ) ) { \
     444forall( istype & | basic_istream( istype ) ) { \
    437445        istype & ?|?( istype & is, _Istream_Manip(T) f ); \
    438446        void ?|?( istype & is, _Istream_Manip(T) f ); \
  • libcfa/src/strstream.cfa

    ra6c45c6 r2d8a770  
    1010// Created On       : Thu Apr 22 22:24:35 2021
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Sat Apr 24 11:15:47 2021
    13 // Update Count     : 73
     12// Last Modified On : Tue Apr 27 20:59:53 2021
     13// Update Count     : 78
    1414//
    1515
     
    2323#include <unistd.h>                                                                             // sbrk, sysconf
    2424
     25
    2526// *********************************** strstream ***********************************
    2627
     
    2930
    3031// private
    31 bool sepPrt$( strstream & os ) { setNL$( os, false ); return os.sepOnOff$; }
    32 void sepReset$( strstream & os ) { os.sepOnOff$ = os.sepDefault$; }
    33 void sepReset$( strstream & os, bool reset ) { os.sepDefault$ = reset; os.sepOnOff$ = os.sepDefault$; }
    34 const char * sepGetCur$( strstream & os ) { return os.sepCur$; }
    35 void sepSetCur$( strstream & os, const char sepCur[] ) { os.sepCur$ = sepCur; }
    36 bool getNL$( strstream & os ) { return os.sawNL$; }
    37 void setNL$( strstream & os, bool state ) { os.sawNL$ = state; }
    38 bool getANL$( strstream & os ) { return os.nlOnOff$; }
    39 bool getPrt$( strstream & os ) { return os.prt$; }
    40 void setPrt$( strstream & os, bool state ) { os.prt$ = state; }
     32bool sepPrt$( ostrstream & os ) { setNL$( os, false ); return os.sepOnOff$; }
     33void sepReset$( ostrstream & os ) { os.sepOnOff$ = os.sepDefault$; }
     34void sepReset$( ostrstream & os, bool reset ) { os.sepDefault$ = reset; os.sepOnOff$ = os.sepDefault$; }
     35const char * sepGetCur$( ostrstream & os ) { return os.sepCur$; }
     36void sepSetCur$( ostrstream & os, const char sepCur[] ) { os.sepCur$ = sepCur; }
     37bool getNL$( ostrstream & os ) { return os.sawNL$; }
     38void setNL$( ostrstream & os, bool state ) { os.sawNL$ = state; }
     39bool getANL$( ostrstream & os ) { return os.nlOnOff$; }
     40bool getPrt$( ostrstream & os ) { return os.prt$; }
     41void setPrt$( ostrstream & os, bool state ) { os.prt$ = state; }
    4142
    4243// public
    43 void ?{}( strstream & os, char buf[], size_t size ) {
     44void ?{}( ostrstream & os, char buf[], size_t size ) {
    4445        os.buf$ = buf;
    4546        os.size$ = size;
     
    5556} // ?{}
    5657
    57 void sepOn( strstream & os ) { os.sepOnOff$ = ! getNL$( os ); }
    58 void sepOff( strstream & os ) { os.sepOnOff$ = false; }
     58void sepOn( ostrstream & os ) { os.sepOnOff$ = ! getNL$( os ); }
     59void sepOff( ostrstream & os ) { os.sepOnOff$ = false; }
    5960
    60 bool sepDisable( strstream & os ) {
     61bool sepDisable( ostrstream & os ) {
    6162        bool temp = os.sepDefault$;
    6263        os.sepDefault$ = false;
     
    6566} // sepDisable
    6667
    67 bool sepEnable( strstream & os ) {
     68bool sepEnable( ostrstream & os ) {
    6869        bool temp = os.sepDefault$;
    6970        os.sepDefault$ = true;
     
    7273} // sepEnable
    7374
    74 void nlOn( strstream & os ) { os.nlOnOff$ = true; }
    75 void nlOff( strstream & os ) { os.nlOnOff$ = false; }
     75void nlOn( ostrstream & os ) { os.nlOnOff$ = true; }
     76void nlOff( ostrstream & os ) { os.nlOnOff$ = false; }
    7677
    77 const char * sepGet( strstream & os ) { return os.separator$; }
    78 void sepSet( strstream & os, const char s[] ) {
     78const char * sepGet( ostrstream & os ) { return os.separator$; }
     79void sepSet( ostrstream & os, const char s[] ) {
    7980        assert( s );
    80         strncpy( os.separator$, s, strstream_sepSize - 1 );
    81         os.separator$[strstream_sepSize - 1] = '\0';
     81        strncpy( os.separator$, s, ostrstream_sepSize - 1 );
     82        os.separator$[ostrstream_sepSize - 1] = '\0';
    8283} // sepSet
    8384
    84 const char * sepGetTuple( strstream & os ) { return os.tupleSeparator$; }
    85 void sepSetTuple( strstream & os, const char s[] ) {
     85const char * sepGetTuple( ostrstream & os ) { return os.tupleSeparator$; }
     86void sepSetTuple( ostrstream & os, const char s[] ) {
    8687        assert( s );
    87         strncpy( os.tupleSeparator$, s, strstream_sepSize - 1 );
    88         os.tupleSeparator$[strstream_sepSize - 1] = '\0';
     88        strncpy( os.tupleSeparator$, s, ostrstream_sepSize - 1 );
     89        os.tupleSeparator$[ostrstream_sepSize - 1] = '\0';
    8990} // sepSet
    9091
    91 void ends( strstream & os ) {
     92void ends( ostrstream & os ) {
    9293        if ( getANL$( os ) ) nl( os );
    9394        else setPrt$( os, false );                                                      // turn off
    9495} // ends
    9596
    96 int fmt( strstream & os, const char format[], ... ) {
     97int fmt( ostrstream & os, const char format[], ... ) {
    9798        va_list args;
    9899        va_start( args, format );
    99100        int len = vsnprintf( os.buf$ + os.cursor$, os.size$ - os.cursor$, format, args );
     101        va_end( args );
    100102        os.cursor$ += len;
    101103        if ( os.cursor$ >= os.size$ ) {                                         // cursor exceeded buffer size?
    102                 #define fmtmsg IO_MSG "strstream truncated write, buffer too small.\n"
     104                #define fmtmsg IO_MSG "ostrstream truncated write, buffer too small.\n"
    103105                write( STDERR_FILENO, fmtmsg, sizeof(fmtmsg) - 1 );
    104106                abort();
    105107        } // if
    106         va_end( args );
    107108
    108109        setPrt$( os, true );                                                            // called in output cascade
     
    111112} // fmt
    112113
    113 int flush( strstream & ) {                                                              // match trait, not used
    114         return 0;
    115 } // flush
    116 
    117 strstream & write( strstream & os ) {
    118         return write( os, stdout );
    119 } // write
    120 strstream & write( strstream & os, FILE * stream ) {
     114ostrstream & write( ostrstream & os, FILE * stream ) {
    121115        if ( fwrite( os.buf$, 1, os.cursor$, stream ) != os.cursor$ ) {
    122                 #define writemsg IO_MSG "strstream write error.\n"
    123                 write( STDERR_FILENO, writemsg, sizeof(writemsg) - 1 );
     116                #define ostrwritemsg IO_MSG "ostrstream write error.\n"
     117                write( STDERR_FILENO, ostrwritemsg, sizeof(ostrwritemsg) - 1 );
    124118                abort();
    125119        } // if
     
    127121} // write
    128122
    129 strstream & sstr;
     123ostrstream & write( ostrstream & os ) {
     124        return write( os, stdout );
     125} // write
     126
     127
     128// *********************************** istrstream ***********************************
     129
     130
     131// public
     132void ?{}( istrstream & is, char buf[] ) {
     133        is.buf$ = buf;
     134        is.cursor$ = 0;
     135        is.nlOnOff$ = false;
     136} // ?{}
     137
     138bool getANL( istrstream & is ) { return is.nlOnOff$; }
     139void nlOn( istrstream & is ) { is.nlOnOff$ = true; }
     140void nlOff( istrstream & is ) { is.nlOnOff$ = false; }
     141
     142void ends( istrstream & is ) {
     143} // ends
     144
     145int eof( istrstream & is ) {
     146        return 0;
     147} // eof
     148
     149istrstream &ungetc( istrstream & is, char c ) {
     150        // if ( ungetc( c, (FILE *)(is.file$) ) == EOF ) {
     151        //      abort | IO_MSG "ungetc" | nl | strerror( errno );
     152        // } // if
     153        return is;
     154} // ungetc
     155
     156int fmt( istrstream & is, const char format[], ... ) {
     157        va_list args;
     158        va_start( args, format );
     159        // This does not work because vsscanf does not return buffer position.
     160        int len = vsscanf( is.buf$ + is.cursor$, format, args );
     161        va_end( args );
     162        if ( len == EOF ) {
     163                int j;
     164                printf( "X %d%n\n", len, &j );
     165        } // if
     166        is.cursor$ += len;
     167        return len;
     168} // fmt
    130169
    131170// Local Variables: //
  • libcfa/src/strstream.hfa

    ra6c45c6 r2d8a770  
    1010// Created On       : Thu Apr 22 22:20:59 2021
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Sat Apr 24 11:17:33 2021
    13 // Update Count     : 37
     12// Last Modified On : Tue Apr 27 20:58:50 2021
     13// Update Count     : 41
    1414//
    1515
     
    2020
    2121
    22 // *********************************** strstream ***********************************
     22// *********************************** ostrstream ***********************************
    2323
    2424
    25 enum { strstream_sepSize = 16 };
    26 struct strstream {                                                                              // satisfied basic_ostream
     25enum { ostrstream_sepSize = 16 };
     26struct ostrstream {                                                                             // satisfied basic_ostream
    2727        char * buf$;
    2828        size_t size$;
     
    3434        bool sawNL$;
    3535        const char * sepCur$;
    36         char separator$[strstream_sepSize];
    37         char tupleSeparator$[strstream_sepSize];
    38 }; // strstream
     36        char separator$[ostrstream_sepSize];
     37        char tupleSeparator$[ostrstream_sepSize];
     38}; // ostrstream
    3939
    4040// Satisfies basic_ostream
    4141
    4242// private
    43 bool sepPrt$( strstream & );
    44 void sepReset$( strstream & );
    45 void sepReset$( strstream &, bool );
    46 const char * sepGetCur$( strstream & );
    47 void sepSetCur$( strstream &, const char [] );
    48 bool getNL$( strstream & );
    49 void setNL$( strstream &, bool );
    50 bool getANL$( strstream & );
    51 bool getPrt$( strstream & );
    52 void setPrt$( strstream &, bool );
     43bool sepPrt$( ostrstream & );
     44void sepReset$( ostrstream & );
     45void sepReset$( ostrstream &, bool );
     46const char * sepGetCur$( ostrstream & );
     47void sepSetCur$( ostrstream &, const char [] );
     48bool getNL$( ostrstream & );
     49void setNL$( ostrstream &, bool );
     50bool getANL$( ostrstream & );
     51bool getPrt$( ostrstream & );
     52void setPrt$( ostrstream &, bool );
    5353
    5454// public
    55 void sepOn( strstream & );
    56 void sepOff( strstream & );
    57 bool sepDisable( strstream & );
    58 bool sepEnable( strstream & );
    59 void nlOn( strstream & );
    60 void nlOff( strstream & );
     55void sepOn( ostrstream & );
     56void sepOff( ostrstream & );
     57bool sepDisable( ostrstream & );
     58bool sepEnable( ostrstream & );
     59void nlOn( ostrstream & );
     60void nlOff( ostrstream & );
    6161
    62 const char * sepGet( strstream & );
    63 void sepSet( strstream &, const char [] );
    64 const char * sepGetTuple( strstream & );
    65 void sepSetTuple( strstream &, const char [] );
     62const char * sepGet( ostrstream & );
     63void sepSet( ostrstream &, const char [] );
     64const char * sepGetTuple( ostrstream & );
     65void sepSetTuple( ostrstream &, const char [] );
    6666
    67 void ends( strstream & );
    68 int fmt( strstream &, const char format[], ... ) __attribute__(( format(printf, 2, 3) ));
    69 int flush( strstream & );
     67void ends( ostrstream & );
     68int fmt( ostrstream &, const char format[], ... ) __attribute__(( format(printf, 2, 3) ));
    7069
    71 strstream & write( strstream & os );                                    // use stdout, default value not working
    72 strstream & write( strstream & os, FILE * stream = stdout );
     70ostrstream & write( ostrstream & os, FILE * stream ); // FIX ME: use default = stdout
     71ostrstream & write( ostrstream & os );
    7372
    74 void ?{}( strstream &, char buf[], size_t size );
     73void ?{}( ostrstream &, char buf[], size_t size );
    7574
    76 extern strstream & sstr;
     75
     76// *********************************** istrstream ***********************************
     77
     78
     79struct istrstream {
     80        char * buf$;
     81        size_t cursor$;
     82        bool nlOnOff$;
     83}; // istrstream
     84
     85// Satisfies basic_istream
     86
     87// public
     88bool getANL( istrstream & );
     89void nlOn( istrstream & );
     90void nlOff( istrstream & );
     91void ends( istrstream & );
     92int fmt( istrstream &, const char format[], ... ) __attribute__(( format(scanf, 2, 3) ));
     93istrstream & ungetc( istrstream & is, char c );
     94int eof( istrstream & is );
     95
     96void ?{}( istrstream & is, char buf[] );
    7797
    7898// Local Variables: //
  • src/Parser/parser.yy

    ra6c45c6 r2d8a770  
    1010// Created On       : Sat Sep  1 20:22:55 2001
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Wed Apr 14 18:13:44 2021
    13 // Update Count     : 4983
     12// Last Modified On : Mon Apr 26 18:41:54 2021
     13// Update Count     : 4990
    1414//
    1515
     
    211211} // forCtrl
    212212
    213 bool forall = false, yyy = false;                                               // aggregate have one or more forall qualifiers ?
     213bool forall = false;                                                                    // aggregate have one or more forall qualifiers ?
    214214
    215215// https://www.gnu.org/software/bison/manual/bison.html#Location-Type
     
    812812                { $$ = new ExpressionNode( build_cast( $2, $4 ) ); }
    813813        | '(' aggregate_control '&' ')' cast_expression         // CFA
     814                { $$ = new ExpressionNode( build_keyword_cast( $2, $5 ) ); }
     815        | '(' aggregate_control '*' ')' cast_expression         // CFA
    814816                { $$ = new ExpressionNode( build_keyword_cast( $2, $5 ) ); }
    815817        | '(' VIRTUAL ')' cast_expression                                       // CFA
     
    21282130aggregate_data:
    21292131        STRUCT vtable_opt
    2130                 { yyy = true; $$ = AggregateDecl::Struct; }
     2132                { $$ = AggregateDecl::Struct; }
    21312133        | UNION
    2132                 { yyy = true; $$ = AggregateDecl::Union; }
     2134                { $$ = AggregateDecl::Union; }
    21332135        | EXCEPTION                                                                                     // CFA
    2134                 { yyy = true; $$ = AggregateDecl::Exception; }
     2136                { $$ = AggregateDecl::Exception; }
    21352137          //            { SemanticError( yylloc, "exception aggregate is currently unimplemented." ); $$ = AggregateDecl::NoAggregate; }
    21362138        ;
     
    21382140aggregate_control:                                                                              // CFA
    21392141        MONITOR
    2140                 { yyy = true; $$ = AggregateDecl::Monitor; }
     2142                { $$ = AggregateDecl::Monitor; }
    21412143        | MUTEX STRUCT
    2142                 { yyy = true; $$ = AggregateDecl::Monitor; }
     2144                { $$ = AggregateDecl::Monitor; }
    21432145        | GENERATOR
    2144                 { yyy = true; $$ = AggregateDecl::Generator; }
     2146                { $$ = AggregateDecl::Generator; }
    21452147        | MUTEX GENERATOR
    21462148                { SemanticError( yylloc, "monitor generator is currently unimplemented." ); $$ = AggregateDecl::NoAggregate; }
    21472149        | COROUTINE
    2148                 { yyy = true; $$ = AggregateDecl::Coroutine; }
     2150                { $$ = AggregateDecl::Coroutine; }
    21492151        | MUTEX COROUTINE
    21502152                { SemanticError( yylloc, "monitor coroutine is currently unimplemented." ); $$ = AggregateDecl::NoAggregate; }
    21512153        | THREAD
    2152                 { yyy = true; $$ = AggregateDecl::Thread; }
     2154                { $$ = AggregateDecl::Thread; }
    21532155        | MUTEX THREAD
    21542156                { SemanticError( yylloc, "monitor thread is currently unimplemented." ); $$ = AggregateDecl::NoAggregate; }
  • tests/io/io-acquire.cfa

    ra6c45c6 r2d8a770  
    1010// Created On       : Mon Mar  1 18:40:09 2021
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Tue Mar  2 12:06:35 2021
    13 // Update Count     : 17
     12// Last Modified On : Tue Apr 27 11:49:34 2021
     13// Update Count     : 18
    1414//
    1515
     
    4343        int a, b, c, d, e, f, g, h, i;
    4444        for ( 100 ) {                                                                           // local protection
    45                 sin  | acquire | a | b | c | d | e | f | g | h | i;
     45                sin | acquire | a | b | c | d | e | f | g | h | i;
    4646        }
    4747        {                                                                                                       // global protection (RAII)
  • tests/strstream.cfa

    ra6c45c6 r2d8a770  
     1//
     2// Cforall Version 1.0.0 Copyright (C) 2021 University of Waterloo
     3//
     4// strstream.cfa --
     5//
     6// Author           : Peter A. Buhr
     7// Created On       : Wed Apr 28 21:47:35 2021
     8// Last Modified By : Peter A. Buhr
     9// Last Modified On : Wed Apr 28 21:50:02 2021
     10// Update Count     : 3
     11//
     12
    113#include <fstream.hfa>
    214#include <strstream.hfa>
    315
    416int main() {
    5     enum { size = 256 };
    6     char buf[size];
    7     strstream sstr = { buf, size };
    8     int i = 3, j = 5, k = 7;
    9     double x = 12345678.9, y = 98765.4321e-11;
     17        enum { size = 256 };
     18        char buf[size];                                                                         // output buffer
     19        ostrstream osstr = { buf, size };                                       // bind output buffer/size
     20        int i = 3, j = 5, k = 7;
     21        double x = 12345678.9, y = 98765.4321e-11;
    1022
    11     sstr | i | hex(j) | wd(10, k) | sci(x) | unit(eng(y));
    12     write( sstr );
    13     printf( "%s", buf );
    14     sout | i | hex(j) | wd(10, k) | sci(x) | unit(eng(y));
     23        osstr | i | hex(j) | wd(10, k) | sci(x) | unit(eng(y)); // same lines of output
     24        write( osstr );
     25        printf( "%s", buf );
     26        sout | i | hex(j) | wd(10, k) | sci(x) | unit(eng(y));
     27
     28        // char buf2[] = "12 14 15 3.5 7e4";                                    // input buffer
     29        // istrstream isstr = { buf2 };
     30        // isstr | i | j | k | x | y;
     31        // sout | i | j | k | x | y;
    1532}
     33
     34// Local Variables: //
     35// tab-width: 4 //
     36// compile-command: "cfa strstream.cfa" //
     37// End: //
Note: See TracChangeset for help on using the changeset viewer.