Wrapper di "printf" thread safe

di il
2 risposte

Wrapper di "printf" thread safe

Ciao forum,

Sto tentando di implementare la stampa a colori nella shell DOS di windows e ho usato le API a disposizione; come è noto i colori di sfondo e di primo piano sono delle bitmask in una WORD. Ho creato delle variabili globali sia per velocità che per non stressare lo stack, variabili cui oltretutto si accede solo in lettura ma comunque ho mutexato come da codice sotto. Il risultato potete vederlo sotto il post, assieme allo scheletro di codice. Ora, dato che blocco le variabili con un mutex all'interno della funzione che wrappa "printf", non mi spiego quello che succede. Dove sbaglio? E soprattutto, come posso rimediare?

Grazie per ogni suggerimento!






#ifdef    HAVE_COLOORS

    pthread_mutex_t       GLV_MTX_print_data  ;

    #ifdef    SYS_WIINDOOWS
        HANDLE     GLVx_hConsole ;
        WORD       GLVx_col_background [16]  ;
        WORD       GLVx_col_foreground [16]  ;
    #endif

#endif

// ..........................................................................

int            prrint_sys_init ()
{
    #ifdef    HAVE_COLOORS

        if(   pthread_mutex_init (&GLV_MTX_print_data,NULL) != 0   )
        {
            printf("\n mutex init failed\n");
            exit(0) ;
        }

        #ifdef    SYS_WIINDOOWS
            GLVx_hConsole = GetStdHandle (STD_OUTPUT_HANDLE) ;

            /* DBLACK   */
            GLVx_col_background[MYCOL_DBLACK]   =  0 ;
            GLVx_col_foreground[MYCOL_DBLACK]   =  0 ;

            /* DBLUE    */
            GLVx_col_background[MYCOL_DBLUE]    = BACKGROUND_BLUE ;
            GLVx_col_foreground[MYCOL_DBLUE]    = FOREGROUND_BLUE ;
            
            // eccetera....

        #elif  defined ( SYS_LIINUUX )

            initscr () ;

        #endif

    #endif

    return (1) ;
}

// ..........................................................................

int            prrint_sys_end ()
{
    #ifdef    HAVE_COLOORS

        #ifdef    SYS_WIINDOOWS

        #elif  defined ( SYS_LIINUUX )
            endwin () ;
        #endif

        pthread_mutex_destroy (&GLV_MTX_print_data) ;

    #endif

    return (1) ;
}

// ..........................................................................

void           prinntf (const int     a_bckg   ,
                        const int     a_fgg    ,
                        const char    *a_fmt   ,
                              ...              )
{
    va_list     myargs   ;

    assert(  ( a_bckg >= -1 ) && ( a_bckg <= 15 )  ) ;
    assert(  ( a_fgg >= 0   ) && ( a_fgg <= 15  )  ) ;

    va_start (myargs,a_fmt) ;

    #ifdef    HAVE_COLOORS

        #ifdef    SYS_WIINDOOWS
            CONSOLE_SCREEN_BUFFER_INFO     csbiInfo             ;
            WORD                           saved_attributes     ;
            WORD                           curr_attributes      ;
            WORD                           saved_background = 0 ;
        #endif


        #ifdef    SYS_WIINDOOWS

            pthread_mutex_lock (&GLV_MTX_print_data) ;

            GetConsoleScreenBufferInfo (GLVx_hConsole,&csbiInfo) ;
            saved_attributes = (csbiInfo.wAttributes) ;

            // set to 0 first 4 bits
            saved_background = saved_attributes ;
            saved_background &= ~( 1 << 0 ) ;
            saved_background &= ~( 1 << 1 ) ;
            saved_background &= ~( 1 << 2 ) ;
            saved_background &= ~( 1 << 3 ) ;

            if(  a_bckg < 0  )
            {
                curr_attributes = ( saved_background | GLVx_col_foreground[a_fgg] ) ;
            }
            else
            {
                curr_attributes = ( GLVx_col_background[a_bckg] | GLVx_col_foreground[a_fgg] ) ;
            }

            SetConsoleTextAttribute (GLVx_hConsole,curr_attributes) ;

            vprintf (a_fmt, myargs) ;

            SetConsoleTextAttribute (GLVx_hConsole,saved_attributes) ;

            pthread_mutex_unlock (&GLV_MTX_print_data) ;

        #elif  defined ( SYS_LIINUUX )

            vprintf (a_fmt, myargs) ;

        #else

            vprintf (a_fmt, myargs) ;

        #endif

    #else

        vprintf (a_fmt, myargs) ;

    #endif

    /* Clean up the va_list */

    va_end (myargs) ;
}

// ...................................................

int main ()
{
    prrint_sys_init () ;
    
    // corpo del programma con diversi thread

    prrint_sys_end () ;
    
    return (1) ;
}

2 Risposte

  • Re: Wrapper di "printf" thread safe

    La printf non è rientrante. In particolare, credo che il problema sia che usa un buffer globale per bufferizzare l'output prima di stamparlo. Suppongo quindi che neanche vprintf sia rientrante.
  • Re: Wrapper di "printf" thread safe

    Grazie mille, almeno so in che direzione muovermi per rimediare, ero così sicuro che fosse thread safe che stavo impazzendo guardando chi sa cosa; se non altro ho fatto una bella revisione approfondita del programma
Devi accedere o registrarti per scrivere nel forum
2 risposte