Visualizzazione dei risultati da 1 a 8 su 8
  1. #1

    [C++ Win32] CRITICAL SECTION in server multi-thread

    Salve,

    sto creando una piccola applicazione basata sugli eventi per fare in modo che il thread principale Producer e vari threads Consumer comunichino tra di loro l'accesso ad una area di memoria condivisa. Il compito dei threads Consumer è di registrare la loro presenza (il loro buffer + il loro HANDLE) dentro a delle mappe con chiave unica data da: GetCurrentThreadId().

    Tuttavia, i vari thread fanno uso di una sola mappa (std::map) con scope globale. Quindi è necessario implementare una mutua esclusione.

    Mi è stato consigliato dapprima di usare boost::mutex (anche perchè portabile) e poi i vari mutex forniti dalla piattaforma win32. Ma alla fine mi è stato consigliato di preferire la sezione critica di win32 ovvero: CRITICAL_SECTION

    Essendo per me una cosa nuova non saprei come implementarla nel mio progetto, per questo vi posto un codice di esempio che replica in breve lo scenario che mi trovo ad affrontare:

    codice:
    // Buffer structs "circular"
    
    struct buffer
    {
        unsigned char data[1024];   // binary data container
        int bytesRecorded;          // bytes actually written (to read)
        int flag;                   // Empty/filled (enum)
        buffer(...);                // constructor()
    }; 
    
    struct circular
    {
        circular_buffer<buffer> cb; // Cicular buffer based on "buffer"
    };
    
    // Global maps
    
    map<int, circular> users;
    map<int, circular>::iterator uit;
    map<int, HANDLE> eventi; 
    
    int main()
    {
    	// TODO: launch Producer thread.
    	(...)
    
    	// TODO: Set up server and accept incoming
    	// requests. Each time a client connects
    	// spawn a new Consumer thread
    	(...)
    
    	return 0; // never for the moment!
    }
    
    // Thread Consumer is launched
    // anytime a client conencts.
    
    thread Consumer
    {
    	int threadid = (int)GetCurrentThreadId();
    
        	// Create event & push it in the "eventi" map
    	//
        	HANDLE hevent = CreateEvent(NULL,0,0,NULL);
        	eventi.insert(make_pair(threadid, hevent));
    
    	// Prepare & add circular buffer to the "users" map
    	//
        	circular c; 
    	users.insert(make_pair(threadid, c)); 
    
    	// Loop...
    	//
    	while(1)
    	{
    		// Callback event
    		WaitForSingleObject(eventi[threadid], INFINITE); 
    
    		// TODO: read buffer from "users" map
    		// and send it to the client. If the
    		// client disconnect break the while loop
    	}
    
     	// Close & remove event from event map
    	//
        	CloseHandle(eventi[threadid]);
        	eventi.erase(threadid);
    
    	// Remove buffer from the map
    	//
    	users.erase(threadid);
    
    	return 0;
    }
    
    // Thread Producer is launched
    // once. Its main goal is to write
    // the same data to all the Consumer
    // threads.
    
    thread Producer
    {
    	while(1)
    	{
    		// TODO: write on every
    		// element of map "users"
    		//
    		for(uit=users.begin(); uit!=users.end(); ++uit)
    		{
    			users[uit->first].cb.push_back(buffer(...));
    
    			// Signal event in the Cosumer
    			// thread (buffer written).
    			//
    			if(eventi[uit->first])
                			SetEvent(eventi[uit->first]); 
    		}
    	}
    	return 0;
    }
    come potrei implementare l'uso della CRITICAL_SECTION ??

    grazie
    Alla batteria dai retta ballA

  2. #2
    ho provato ad implementarle...ma ottengo degli unhandle exception (writing location)...a questo punto non so più che fare...

    Codice PHP:
    /*
     *
     * Streaming Server v1.1 by THEARTOFWEB Software
     *
     */

    #include <iostream>
    #include <string>
    #include <map>
    #include <algorithm>
    #include <process.h>
    #include <cstdlib>
    #include <ctime>
    #include "socket.h"
    #include <boost/circular_buffer.hpp>
    using namespace std;
    using namespace boost;

    const 
    string CRLF "\r\n";
    const 
    int numbuff 3;

    unsigned int __stdcall Consumer(voidsock);
    unsigned int __stdcall Producer(void*);

    void getDateTime(char szTime);

    enum buffer_status
    {
        
    BUFF_DONE  1,
        
    BUFF_EMPTY 0
    };

    struct buffer
    {
        
    unsigned char data[1024];
        
    int bytesRecorded;
        
    int flag;
        
    buffer(const unsigned char data_, const int bytesRecorded_, const int flag_) :
            
    bytesRecorded(bytesRecorded_), flag(flag_)
            {
                
    copy(data_data_ bytesRecorded_data);
            }
    };

    struct circular
    {
        
    circular_buffer<buffercb;
    };

    // Global maps

    map<intcircularusers;
    map<intcircular>::iterator uit;
    map<intHANDLEeventi;
    map<intHANDLE>::iterator eit;

    // Declare Procuder && Cosumer CS

    CRITICAL_SECTION csProducer;
    CRITICAL_SECTION csConsumer;

    int main()
    {
        
    // Initialize the critical section
        
    InitializeCriticalSection(&csProducer);

        
    // Launch Producer Thread
        
    unsigned int prodRet;
        
    _beginthreadex(0,0,Producer,NULL,0,&prodRet);
        if(
    prodRet)
            
    cout << "Launched Producer Thread!" << endl;

        
    // Release resources used by the critical section object.
        
    DeleteCriticalSection(&csProducer);

        
    // Server.
        // Set up server (port: 8000, maxconn: 10)
        //
        
    SocketServer sockIn(800010);

        while(
    1)
        {
            
    // ...wait for incoming connections...
            
    SocketsockIn.Accept();

            
    // Initialize the critical section
            
    InitializeCriticalSection(&csConsumer);

            
    // Spawn a new Consumr Thread each
            // time a client connects.
            
    unsigned int sockRet;
            
    _beginthreadex(0,0,Consumer,s,0,&sockRet);
            if(
    sockRet)
                
    cout << "Spawned a new thread!" << endl;

            
    // Release resources used by the critical section object.
            
    DeleteCriticalSection(&csConsumer);
        }

        
    sockIn.Close();

        return 
    EXIT_SUCCESS;
    }

    // Consumer Thread
    unsigned int __stdcall Consumer(voidsock)
    {
        
    Socket= (Socket*) sock;

        
    s->SendBytes("Hello World!" CRLF);

        
    int threadid = (int)GetCurrentThreadId();

        
    // Create Event && Push it in the event map
        
    HANDLE hevent CreateEvent(NULL,FALSE,FALSE,NULL);
        
    eventi.insert(make_pair(threadid,hevent));

        
    // Prepare && Add circular buffer to the map
        
    circular c;
        
    c.cb.set_capacity(numbuff);

        for(
    int i 0i<numbuffi++)
        {
            
    c.cb.push_back(buffer(NULL,0,BUFF_EMPTY));
        }

        
    users.insert(make_pair(threadidc));

        
    //
        // Read data from the buffer
        // and send it to the client
        //
        // When using push_back the oldest
        // element in the circular buffer
        // will be in the index 0
        //

        
    Sleep(500);

        while(
    1)
        {
            
    // CALLBACK EVENT
            
    WaitForSingleObject(eventi[threadid], INFINITE);

            if(
    users[threadid].cb.at(0).flag == BUFF_DONE)
            {
                
    string line = (char*)users[threadid].cb.at(0).data;
                
    int ret s->SendBytes(line CRLF);
                if(
    SOCKET_ERROR == ret)
                    break;
            }
        }

        
    // Close & remove event from event map
        
    CloseHandle(eventi[threadid]);

        
    // Request ownership of the critical section.
        
    EnterCriticalSection(&csConsumer);

        
    eventi.erase(threadid);

        
    // Release ownership of the critical section.
        
    LeaveCriticalSection(&csConsumer);

        
    // Remove buffer from the map
        
    users.erase(threadid);

        
    // Say bye to the client
        
    s->SendBytes("Bye bye!" CRLF);

        
    // Disconnect client
        
    cout << "Closing thread..." << endl;
        
    s->Close();
        
    delete s;
        return 
    0;
    }

    // Producer Thread
    unsigned int __stdcall Producer(void*)
    {
        while(
    1)
        {
            
    Sleep(1000);
            
    char szTime[30]; getDateTime(szTime);

            for(
    uit=users.begin(); uit!=users.end(); ++uit)
            {
                
    // Request ownership of the critical section.
                
    EnterCriticalSection(&csProducer);

                
    users[uit->first].cb.push_back(buffer((unsigned char*)szTime30BUFF_DONE));

                if(
    eventi[uit->first])
                    
    SetEvent(eventi[uit->first]);

                
    // Release ownership of the critical section.
                
    LeaveCriticalSection(&csProducer);

                
    cout << "Producer is writing to: " << uit->first << endl;
            }

        }
        return 
    0;
    }

    void getDateTime(char szTime)
    {
        
    time_t rawtime time(NULL);
        
    struct tm timeinfo;
        
    gmtime_s(&timeinfo, &rawtime);
        
    strftime(szTime30"%a, %d %b %Y %X GMT", &timeinfo);

    Alla batteria dai retta ballA

  3. #3
    Utente di HTML.it L'avatar di shodan
    Registrato dal
    Jun 2001
    Messaggi
    2,381
    Mi è stato consigliato dapprima di usare boost::mutex (anche perchè portabile) e poi i vari mutex forniti dalla piattaforma win32. Ma alla fine mi è stato consigliato di preferire la sezione critica di win32 ovvero: CRITICAL_SECTION
    Giusto per chiarezza. boost::mutex è portabile perchè boost è concepita per funzionare su diversi sistemi operativi. Se non hai esigenze di portabilità, puoi usare le primitive di sistema come stai facendo.
    Il fatto è che le usi male. Le CRITICAL_SECTION vanno inizializzate una sola volta prima di far partire i thread e cancellate alla fine e solo se i thread sono terminati.
    codice:
     
        InitializeCriticalSection(&csProducer);
    
        // Launch Producer Thread
        unsigned int prodRet;
        _beginthreadex(0,0,Producer,NULL,0,&prodRet);
        if(prodRet)
            cout << "Launched Producer Thread!" << endl;
    
        // Release resources used by the critical section object.
        DeleteCriticalSection(&csProducer);
    Questo è un errore grave. Una volta lanciato il producer, quello viaggia per i fatti suoi, ma il main continua: cancelli la CRITICAL_SECTION e quando il Producer ci accede hai comportamento indefinito.

    Ancora peggio:
    codice:
        while(1)
        {
            // ...wait for incoming connections...
            Socket* s = sockIn.Accept();
    
            // Initialize the critical section
            InitializeCriticalSection(&csConsumer);
    
            // Spawn a new Consumr Thread each
            // time a client connects.
            unsigned int sockRet;
            _beginthreadex(0,0,Consumer,s,0,&sockRet);
            if(sockRet)
                cout << "Spawned a new thread!" << endl;
    
            // Release resources used by the critical section object.
            DeleteCriticalSection(&csConsumer);
        }
    Qui inizializzi e cancelli le CRITICAL_SECTION in continuazione, col risultato di avere accessi spuri a tutto quanto. E come se non bastasse, non proteggi nemmeno tutte le mappe globali.
    Ricorda che i mutex servono per le mappe, non per i thread, quindi non ha senso chiamare csProducer e csConsumer; meglio chiamarle users_mutex e eventi_mutex

    Queste sono le correzioni da fare, i commenti sono nel codice.

    Codice PHP:
    unsigned int __stdcall Consumer(voidsock);
    unsigned int __stdcall Producer(void*);

    void getDateTime(char szTime);

    enum buffer_status
    {
        
    BUFF_DONE  1,
        
    BUFF_EMPTY 0
    };

    struct buffer
    {
        
    unsigned char data[1024];
        
    int bytesRecorded;
        
    int flag;
        
    buffer(const unsigned char data_, const int bytesRecorded_, const int flag_) :
            
    bytesRecorded(bytesRecorded_), flag(flag_)
            {
                
    copy(data_data_ bytesRecorded_data);
            }
    };

    struct circular
    {
        
    circular_buffer<buffercb;
    };

    // Global maps

    map<intcircularusers;
    map<intHANDLEeventi;

    // Declare Procuder && Cosumer CS

    CRITICAL_SECTION users_mutex;
    CRITICAL_SECTION eventi_mutex;

    int main()
    {
        
    // Initialize all critical sections
        
    InitializeCriticalSection(&users_mutex);
        
    InitializeCriticalSection(&eventi_mutex);

        
    // Launch Producer Thread
        
    unsigned int prodRet;
        
    _beginthreadex(0,0,Producer,NULL,0,&prodRet);
        if(
    prodRet)
            
    cout << "Launched Producer Thread!" << endl;

        
    // Server.
        // Set up server (port: 8000, maxconn: 10)
        //
        
    SocketServer sockIn(800010);

        while(
    1)
        {
            
    // ...wait for incoming connections...
            
    SocketsockIn.Accept();

            
    // Spawn a new Consumr Thread each
            // time a client connects.
            
    unsigned int sockRet;
            
    _beginthreadex(0,0,Consumer,s,0,&sockRet);
            if(
    sockRet)
                
    cout << "Spawned a new thread!" << endl;

        }
        
        
    DeleteCriticalSection(&users_mutex);
        
    DeleteCriticalSection(&eventi_mutex);

        
    sockIn.Close();

        return 
    EXIT_SUCCESS;
    }

    // Consumer Thread
    unsigned int __stdcall Consumer(voidsock)
    {
        
    Socket= (Socket*) sock;

        
    s->SendBytes("Hello World!" CRLF);

        
    int threadid = (int)GetCurrentThreadId();

        
    // Create Event && Push it in the event map
        
    HANDLE hevent CreateEvent(NULL,FALSE,FALSE,NULL);

    //////////////////////////////////////////////////////////////////////////    
        
    EnterCriticalSection(&eventi_mutex); // acquisisce la sezione critica.
        
    eventi.insert(make_pair(threadid,hevent));
        
    LeaveCriticalSection(&eventi_mutex); // rilascia la sezione critica.
    //////////////////////////////////////////////////////////////////////////    
            
            
        // Prepare && Add circular buffer to the map
        
    circular c;
        
    c.cb.set_capacity(numbuff);

        for(
    int i 0i<numbuffi++)
        {
            
    c.cb.push_back(buffer(NULL,0,BUFF_EMPTY));
        }

    //////////////////////////////////////////////////////////////////////////    
        
    EnterCriticalSection(&users_mutex); // acquisisce la sezione critica.
        
    users.insert(make_pair(threadidc));
        
    LeaveCriticalSection(&users_mutex); // rilascia la sezione critica.
    //////////////////////////////////////////////////////////////////////////    


        //
        // Read data from the buffer
        // and send it to the client
        //
        // When using push_back the oldest
        // element in the circular buffer
        // will be in the index 0
        //

        
    Sleep(500);

        while(
    1)
        {
            
    // CALLBACK EVENT
            
    WaitForSingleObject(eventi[threadid], INFINITE);
                    
    // Qui non ci dovrebbe essere una race condition dal momento che ogni consumer
                    // accede a un suo buffer. Nel caso invece ci sia tutto l'if va protetto dal mutex.

            
    if(users[threadid].cb.at(0).flag == BUFF_DONE)
            {
                
    string line = (char*)users[threadid].cb.at(0).data;
                
    int ret s->SendBytes(line CRLF);
                if(
    SOCKET_ERROR == ret)
                    break;
            }
        }

        
    // Close & remove event from event map
        
    CloseHandle(eventi[threadid]);

    //////////////////////////////////////////////////////////////////////////    
        // Request ownership of the critical section.
        
    EnterCriticalSection(&eventi_mutex);
        
    eventi.erase(threadid);
        
    // Release ownership of the critical section.
        
    LeaveCriticalSection(&eventi_mutex);
    //////////////////////////////////////////////////////////////////////////    

    //////////////////////////////////////////////////////////////////////////    
        
    EnterCriticalSection(&users_mutex);
        
    // Remove buffer from the map
        
    users.erase(threadid);
        
    LeaveCriticalSection(&users_mutex);
    //////////////////////////////////////////////////////////////////////////    

        // Say bye to the client
        
    s->SendBytes("Bye bye!" CRLF);

        
    // Disconnect client
        
    cout << "Closing thread..." << endl;
        
    s->Close();
        
    delete s;
        return 
    0;
    }

    // Producer Thread
    unsigned int __stdcall Producer(void*)
    {
        while(
    1)
        {
            
    Sleep(1000);
            
    char szTime[30]; getDateTime(szTime);
            
    // questo iteratore è meglio renderlo locale.
            
    map<intcircular>::iterator uit

        
    // Tutta questa parte va protetta dai mutex perché gli iteratori delle mappe potrebbero
        // essere invalidati da un accesso in scrittura del consumer.
    //////////////////////////////////////////////////////////////////////////    
            // Attenzione!!! L'ordine di rilascio deve avvenire in senso inverso o 
            // si verifica un dead lock. 
            
    EnterCriticalSection(&users_mutex);
            
    EnterCriticalSection(&eventi_mutex);
                    
            for(
    uit=users.begin(); uit!=users.end(); ++uit)
            {

                
    users[uit->first].cb.push_back(buffer((unsigned char*)szTime30BUFF_DONE));

                if(
    eventi[uit->first])
                    
    SetEvent(eventi[uit->first]);

                
    cout << "Producer is writing to: " << uit->first << endl;
            }

            
    LeaveCriticalSection(&eventi_mutex);
            
    LeaveCriticalSection(&users_mutex);
    //////////////////////////////////////////////////////////////////////////    

        
    }
        return 
    0;
    }

    void getDateTime(char szTime)
    {
        
    time_t rawtime time(NULL);
        
    struct tm timeinfo;
        
    gmtime_s(&timeinfo, &rawtime);
        
    strftime(szTime30"%a, %d %b %Y %X GMT", &timeinfo);

    P.S.
    Ho visto che frequenti Usenet. Se ti interessa, c'è il gruppo: comp.programming.threads dove si discute della programmazione multithreading senza distinzione di sistema operativo.
    This code and information is provided "as is" without warranty of any kind, either expressed
    or implied, including but not limited to the implied warranties of merchantability and/or
    fitness for a particular purpose.

  4. #4
    fantastico funzionaaaaaaaaaaa!!!!!!!!!! Inoltre, sicuramente aver spostato map<int, circular>::iterator uit all'interno del producer può aver aituato moltissimo!
    Alla batteria dai retta ballA

  5. #5
    Utente di HTML.it L'avatar di shodan
    Registrato dal
    Jun 2001
    Messaggi
    2,381
    Anche no. Lo usi solo li quindi non potevi avere race condition, però appunto perché lo usi solo li tanto vale renderlo locale. Una prima regola del multithreading è di rendere locale tutto quello che può essere dichiarato all'interno di una funzione e di rendere globale qualcosa solo se indispensabile. A costo di fare capriole col codice.
    Questo per dirti che con due Producer quell'iteratore impazziva.
    This code and information is provided "as is" without warranty of any kind, either expressed
    or implied, including but not limited to the implied warranties of merchantability and/or
    fitness for a particular purpose.

  6. #6
    ti volevo chiedere uan cosa...secondo te questa parte va protetta?

    codice:
    while(1)
    {
      // CALLBACK EVENT
      WaitForSingleObject(eventi[threadid], INFINITE);
    
      if(users[threadid].cb.at(0).flag == BUFF_DONE)
      {
        string line = (char*)users[threadid].cb.at(0).data;
        int ret = s->SendBytes(line + CRLF);
        if(SOCKET_ERROR == ret)
          break;
      }
    }
    grazie
    Alla batteria dai retta ballA

  7. #7
    cmq penso di si...ho apportato altre modifiche:

    codice:
    /*
     *
     * Streaming Server v1.2 by THEARTOFWEB Software
     *
     */
    
    #include <iostream>
    #include <string>
    #include <map>
    #include <algorithm>
    #include <process.h>
    #include <cstdlib>
    #include <ctime>
    #include "socket.h"
    #include <boost/circular_buffer.hpp>
    using namespace std;
    using namespace boost;
    
    const string CRLF = "\r\n";
    const int numbuff = 5;
    
    unsigned int __stdcall Consumer(void* sock);
    unsigned int __stdcall Producer(void*);
    
    void getDateTime(char * szTime);
    
    enum buffer_status
    {
    	BUFF_DONE  = 1,
    	BUFF_EMPTY = 0
    };
    
    struct buffer
    {
    	unsigned char data[1024];
    	int bytesRecorded;
    	int flag;
    	buffer(const unsigned char * data_, const int bytesRecorded_, const int flag_) :
    		bytesRecorded(bytesRecorded_), flag(flag_)
    		{
    			copy(data_, data_ + bytesRecorded_, data);
    		}
    };
    
    struct circular
    {
    	circular_buffer<buffer> cb;
    };
    
    // Global maps
    
    map<int, circular> users;
    CRITICAL_SECTION users_mutex;
    
    map<int, HANDLE> eventi;
    CRITICAL_SECTION eventi_mutex; 
    
    int main()
    {
    	// Initialize all critical sections
    	InitializeCriticalSection(&users_mutex);
    	InitializeCriticalSection(&eventi_mutex); 
    
    	// Launch Producer Thread
    	unsigned int prodRet;
    	_beginthreadex(0,0,Producer,NULL,0,&prodRet);
    	if(prodRet)
    		cout << "Launched Producer Thread!" << endl;
    
    	// Server.
    	// Set up server (port: 8000, maxconn: 10)
    	//
    	SocketServer sockIn(8000, 10);
    
    	while(1)
    	{
    		// ...wait for incoming connections...
    		Socket* s = sockIn.Accept();
    
    		// Spawn a new Consumer Thread each
    		// time a client connects.
    		unsigned int sockRet;
    		_beginthreadex(0,0,Consumer,s,0,&sockRet);
    		if(sockRet)
    			cout << "Spawned a new thread!" << endl;
    
    	}
    
    	DeleteCriticalSection(&users_mutex);
    	DeleteCriticalSection(&eventi_mutex);
    
    	sockIn.Close();
    
    	return EXIT_SUCCESS;
    }
    
    // Consumer Thread
    unsigned int __stdcall Consumer(void* sock)
    {
    	Socket* s = (Socket*) sock;
    
    	s->SendBytes("Hello World!" + CRLF);
    
    	int threadid = (int)GetCurrentThreadId();
    
    	// Create Event && Push it in the "event" map
    	HANDLE hevent = CreateEvent(NULL,FALSE,FALSE,NULL);
    
    	EnterCriticalSection(&eventi_mutex);
    	eventi.insert(make_pair(threadid,hevent));
    	LeaveCriticalSection(&eventi_mutex);
    
    	// Prepare && Add circular buffer to "users" map
    	circular c;
    	c.cb.set_capacity(numbuff);
    
    	for(int i = 0; i<numbuff; i++)
    	{
    		c.cb.push_back(buffer(NULL,0,BUFF_EMPTY));
    	}
    
    	EnterCriticalSection(&users_mutex);
    	users.insert(make_pair(threadid, c));
    	LeaveCriticalSection(&users_mutex);
    
    	//
    	// Read data from the buffer
    	// and send it to the client
    	//
    	// When using push_back the oldest
    	// element in the circular buffer
    	// will be at index 0
    	//
    
    	Sleep(500);
    
    	while(1)
    	{
    		// CALLBACK EVENT
    		WaitForSingleObject(hevent, INFINITE);
    
    		EnterCriticalSection(&users_mutex);
    		int flag = users[threadid].cb.at(0).flag;
    		string line = (char*)users[threadid].cb.at(0).data;
    		LeaveCriticalSection(&users_mutex);
    
    		if(flag == BUFF_DONE)
    		{
    			int ret = s->SendBytes(line + CRLF);
    			if(SOCKET_ERROR == ret)
    				break;
    		}
    	}
    
    	// Close && Remove event from "event" map
    	EnterCriticalSection(&eventi_mutex);
    	eventi.erase(threadid);
    	LeaveCriticalSection(&eventi_mutex);
    	CloseHandle(hevent);
    
    	// Remove buffer from "users" map
    	EnterCriticalSection(&users_mutex);
    	users.erase(threadid);
    	LeaveCriticalSection(&users_mutex);
    
    	// Disconnect client
    	cout << "Closing thread..." << endl;
    
    	s->Close();
    	delete s;
    	return 0;
    }
    
    // Producer Thread
    unsigned int __stdcall Producer(void*)
    {
    	while(1)
    	{
    		Sleep(1000);
    		char szTime[30]; getDateTime(szTime);
    		map<int, circular>::iterator uit;
    
    		EnterCriticalSection(&users_mutex);
    		EnterCriticalSection(&eventi_mutex);
    
    		for(uit=users.begin(); uit!=users.end(); ++uit)
    		{
    			users[uit->first].cb.push_back(buffer((unsigned char*)szTime, 30, BUFF_DONE));
    
    			if(eventi[uit->first])
    				SetEvent(eventi[uit->first]);
    
    			cout << "Producer is writing to: " << uit->first << endl;
    		}
    
    		LeaveCriticalSection(&eventi_mutex);
    		LeaveCriticalSection(&users_mutex);
    	}
    	return 0;
    }
    
    void getDateTime(char * szTime)
    {
    	time_t rawtime = time(NULL);
    	struct tm timeinfo;
    	gmtime_s(&timeinfo, &rawtime);
    	strftime(szTime, 30, "%a, %d %b %Y %X GMT", &timeinfo);
    }
    ancora un'ultima cosa...sei sicuro che questo mi metta completamente al riparo da eventuali deadlocks?

    codice:
    // Producer Thread
    (...)
    EnterCriticalSection(&users_mutex);
    EnterCriticalSection(&eventi_mutex);
    grazie
    Alla batteria dai retta ballA

  8. #8
    Utente di HTML.it L'avatar di shodan
    Registrato dal
    Jun 2001
    Messaggi
    2,381
    ti volevo chiedere uan cosa...secondo te questa parte va protetta?
    In linea teorica non servirebbe proteggerla. Il consumer aspetta fino a quando è sbloccato, poi può accedere in lettura al suo buffer. E visto che solo lo stesso consumer può invalidarla, l'accesso dovrebbe essere safe. In ogni caso te ne accorgeresti.

    ancora un'ultima cosa...sei sicuro che questo mi metta completamente al riparo da eventuali deadlocks?
    Abbastanza da dormirci sonni tranquilli.
    C'è da dire però che questo è un modo "barbaro" di procedere in C++. In C non c'è altro modo, ma in C++ si possono gestire i mutex e i lock usando apposite classi che rendono più semplice leggere il codice.
    This code and information is provided "as is" without warranty of any kind, either expressed
    or implied, including but not limited to the implied warranties of merchantability and/or
    fitness for a particular purpose.

Permessi di invio

  • Non puoi inserire discussioni
  • Non puoi inserire repliche
  • Non puoi inserire allegati
  • Non puoi modificare i tuoi messaggi
  •  
Powered by vBulletin® Version 4.2.1
Copyright © 2025 vBulletin Solutions, Inc. All rights reserved.