PDA

Visualizza la versione completa : Semafori e multithreading (C++Builder 6)


rikkardo
04-05-2006, 14:59
Ciao a tutti,
vi scrivo per chiedervi se conoscete qualche guida (in italiano (meglio) o inglese) che illustri la programmazioni multithreading, il concetto di semafori e magari la sua implementazione in C++.

Grazie

cshark
04-05-2006, 22:16
Proprio questa sera ho realizzato questo esempio per te. Questo è uno dei primi che mostra l'esecuzione separata di due funzioni.
Usando le librerie Borland, creao una classe discendente dalla classe TThread .
La funzione Execute() si occupa dell'esecuzione di ogni singolo processo.
Riporto qui i due file Unit.

----->Questo è il file Software.cpp
#include <vcl.h>
#pragma hdrstop

#include "Software.h"
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
: TForm(Owner)
{
}
//---------------------------------------------------------------------------


void func1()
{
ShowMessage("Primo Thread");
}

void func2()
{
ShowMessage("Secondo Thread");
}


void __fastcall MyThread::Execute()
{
void(*fp)(void)= func1; //Creo i puntatori a funzione e li faccio puntare alle
void (*fp2)(void)= func2; //funzioni func1() e func2()

Synchronize((TThreadMethod&) fp);

Synchronize((TThreadMethod&) fp2);

}

void __fastcall TForm1::Button1Click(TObject *Sender)
{
MyThread *ob = new MyThread(false); //la funzione MyThread::Execute() viene chiamata
//dal costruttore duranre l'inizializzazione dell'oggetto



//Come puoi notare l'argomento del costruttore ereditato da TThread e di tipo boolean
//se è impostato su 'false' i thread vengono eseguiti, altrimenti se è su 'true' rimane sospesi.
}

-------> Questa invece è il file header Software.h

#include <StdCtrls.hpp>
#include <Forms.hpp>

class MyThread: public TThread
{
protected:
void __fastcall Execute();

public:
MyThread(bool CreateSuspended):TThread(CreateSuspended){int boo;}
//ho overridato il costruttore perchè altrimenti non potrebbe essere
//chiamato da un oggetto MyThread perchè in TThread il costruttore sarà protetto
};


class TForm1 : public TForm
{
__published: // IDE-managed Components
TButton *Button1;
void __fastcall Button1Click(TObject *Sender);
private: // User declarations
public: // User declarations
__fastcall TForm1(TComponent* Owner);
};
//---------------------------------------------------------------------------
extern PACKAGE TForm1 *Form1;
//---------------------------------------------------------------------------
#endif






Come è illustato nel sorgente, all'interno della funzione Execute() utilizzo le funzioni Synchronize(). Il sistema operativo Windows, ogni 20 millisecondi esegue un processo, allocando nella memoria di stack cioò che stava eseguendo prima: ad esempio se in un primo momento il computer esegue l'addizione 3+3+3 e deve interromperla, egli alloca nello stack il risultato parziale(cioè 6) e l'operazione che stava eseguendo più l'opendo 3.
La funzione Synchronize viene chiamata ogni 20 millisecondi dal gestore dei Thread del sistema operativo. Synchronize() , una volta chiamata chiama le funzioni che vengono puntate dal puntatore di funzione che fa da argomento.
(TthreadMethod&) è l'operatore di cast che converte il nostro puntatore a funzione, restituendo alla struttura TThreadMethod l'indirizzo del nostro puntatore a funzione.
Se non sbaglio TThreadMethod punta alla memoria di Stack, quindi gestisce i segmenti delle funzioni.



Il programma funziona così: cliccando sul pulsante con il nome Button1 i thread vengono eseguiti. Per quanto riguarda la form, basta che prima crei una finestra con un pulsante TButton. Spero di essere stato chiaro per adesso, spesso divago troppo come adesso...tra poco ti mostrerò altri esempi sull'esecuzione separata dei Thread.

cshark
04-05-2006, 22:43
Devo correggere uno strafalcione. Il costruttore della classe derivata MyThread dev'essere per forza overridato poiche la superclasse TThread è astratta.

alka
05-05-2006, 09:56
Originariamente inviato da cshark
Devo correggere uno strafalcione. Il costruttore della classe derivata MyThread dev'essere per forza overridato poiche la superclasse TThread è astratta.
Il metodo astratto, se non ricordo male, è Execute, e non il costruttore. :master:

O almeno questo è ciò che vale per Delphi, ma trattandosi della stessa identica libreria...

cshark
05-05-2006, 10:45
Originariamente inviato da alka
Il metodo astratto, se non ricordo male, è Execute, e non il costruttore. :master:

O almeno questo è ciò che vale per Delphi, ma trattandosi della stessa identica libreria...

Non capisco però perchè il compilatore ti costringa a implementarlo anche nella classe derivata.
Addirittura bisogna overridare anche il costruttore della superclasse.

cshark
05-05-2006, 10:53
Alka, anche tu implementi il costruttore derivato dalla superclasse in Delphi? Ci sono ancora aspetti delle VCL o del C++ che mi sfuggono ancora. :master:

Anche se Delphi è molto più dinamico e comprensibile.

alka
05-05-2006, 11:03
Originariamente inviato da cshark
Alka, anche tu implementi il costruttore derivato dalla superclasse in Delphi?

No, implemento solamente il metodo Execute, come suggerisce anche il wizard che crea automaticamente lo scheletro di implementazione.

Non ho la possibilità, in questo momento, di verificare cosa succede in C++Builder.

In ogni caso, rimandiamo il discorso in quanto non è del tutto in linea con il contenuto della discussione. Attendiamo un feedback dall'autore originale per vedere se le informazioni espresse sino ad ora sono utili, soprattutto perché chiedeva informazioni generiche e documentazione sui thread e in particolar modo sui semafori, di cui non si è ancora parlato, mentre si è svicolato su altri argomenti e non è proprio una manovra correttissima.

Eventualmente, si aprirà una nuova discussione se è necessario approfondire dubbi sull'implementazione della classe TThread da parte del C++Builder.

Ciao! :ciauz:

cshark
05-05-2006, 11:11
Originariamente inviato da alka
No, implemento solamente il metodo Execute, come suggerisce anche il wizard che crea automaticamente lo scheletro di implementazione.

Non ho la possibilità, in questo momento, di verificare cosa succede in C++Builder.

In ogni caso, rimandiamo il discorso in quanto non è del tutto in linea con il contenuto della discussione. Attendiamo un feedback dall'autore originale per vedere se le informazioni espresse sino ad ora sono utili, soprattutto perché chiedeva informazioni generiche e documentazione sui thread e in particolar modo sui semafori, di cui non si è ancora parlato, mentre si è svicolato su altri argomenti e non è proprio una manovra correttissima.

Eventualmente, si aprirà una nuova discussione se è necessario approfondire dubbi sull'implementazione della classe TThread da parte del C++Builder.

Ciao! :ciauz:

Al momento ho fatto una semplice implementazione di un costrutto. Spero che sia comprensibilissimo. Poi passiamo alla gestione singola dei Thread.

Loading