Torna indietro   Hardware Upgrade Forum > Software > Programmazione

Lenovo IdeaPad Slim 3: un notebook Snapdragon X economico
Lenovo IdeaPad Slim 3: un notebook Snapdragon X economico
Forte della piattaforma Qualcomm Snapdragon X, il notebook Lenovo IdeaPad Slim 3 riesce a coniugare caratteristiche tecniche interessanti ad uno chassis robusto, con autonomia di funzionamento a batteria che va ben oltre la tipica giornata di lavoro. Un notebook dal costo accessibile pensato per l'utilizzo domestico o in ufficio, soprattutto con applicazioni native per architettura ARM
Recensione OnePlus Watch 3 43mm: lo smartwatch che mancava per i polsi più piccoli
Recensione OnePlus Watch 3 43mm: lo smartwatch che mancava per i polsi più piccoli
OnePlus risponde alle esigenze di chi cerca un dispositivo indossabile dalle dimensioni contenute con OnePlus Watch 3 43mm. La versione ridotta del flagship mantiene gran parte delle caratteristiche del modello maggiore, offrendo un'esperienza completa in un formato compatto. Il suo limite più grande è abbastanza ovvio: l'autonomia non è il punto di forza di questo modello, ma si raggiungono comodamente le due giornate piene con un uso normale.
BOOX Note Air4 C è uno spettacolo: il tablet E Ink con Android per lettura e scrittura
BOOX Note Air4 C è uno spettacolo: il tablet E Ink con Android per lettura e scrittura
BOOX Note Air4 C rappresenta l'ultima incarnazione della categoria dei tablet E Ink a colori di Onyx, e combina le prestazioni di un dispositivo Android con l'ottima tecnologia Kaleido 3 per il display. Con schermo da 10,3 pollici, un processore Qualcomm Snapdragon 750G e 6 GB di RAM, promette un'esperienza completa per lettura, scrittura e produttività. Il prezzo lo posiziona nel segmento premium, ma questo dispositivo è un vero spettacolo!
Tutti gli articoli Tutte le news

Vai al Forum
Rispondi
 
Strumenti
Old 23-12-2009, 16:27   #1
Teo@Unix
Senior Member
 
L'Avatar di Teo@Unix
 
Iscritto dal: Mar 2009
Messaggi: 753
[C++] Qt multithreading

Ho un quesito per quanto riguarda la programmazione con più di 2 thread....

se io ho 3 classi, una la struttura dati, le altre due devono accedervi spesso. Siccome non è possibile prevedere e conseguentemente sincronizzare gli accessi, utilizzo la classe QMutex per evitare accessi contemporanei....
La mia domanda è...
questa classe la utilizzo dentro i metodi pubblici della classe per i dati? è corretto?

Non mi interessa inserire QMutex dentro le altre due, ok?

Quindi dentro ogni metodo per esempio un metodo "get" farei così:
Codice:
QString charon::get_Host()
{
    QString temp;
    Mutex.lock();
    temp = Host;
    Mutex.unlock();
    return(temp);
}
dove "Host" è un elemento della struttura dati.
secondo voi?
Grazie.

Ultima modifica di Teo@Unix : 23-12-2009 alle 16:29.
Teo@Unix è offline   Rispondi citando il messaggio o parte di esso
Old 24-12-2009, 01:55   #2
Black imp
Senior Member
 
Iscritto dal: Nov 2000
Città: MILANO
Messaggi: 2662
ad occhio e croce si. si sincronizza la classe che ha i dati cui si vuole accedere in modo esclusivo. quindi nei metodi della classe con i dati, che devono essere chiamati dalle altre due classi, si alza un mutex nella parte di codice chiamato critical race, che di solito è un membro - privato direi - della classe dati. quando uno arriva e trova il mutex lockato aspetta. occhio ai deadlock.
Black imp è offline   Rispondi citando il messaggio o parte di esso
Old 24-12-2009, 09:15   #3
cionci
Senior Member
 
L'Avatar di cionci
 
Iscritto dal: Apr 2000
Città: Vicino a Montecatini(Pistoia) Moto:Kawasaki Ninja ZX-9R Scudetti: 29
Messaggi: 53971
Il valore di host viene mai cambiato ? Sui valori read-only non c'è bisogno di alcuna sincronizzazione.
La sincronizzazione c'è bisogno solamente in caso di read e write concorrenti o di write concorrenti su operazioni non atomiche.
Per andare oltre dovresti studiarti qualche manuale sulla programmazione concorrente, perché esistono tanti, ma tanti trucchi per diminuire i conflitti sulle risorse.

Ultima modifica di cionci : 24-12-2009 alle 09:26.
cionci è offline   Rispondi citando il messaggio o parte di esso
Old 24-12-2009, 09:28   #4
Teo@Unix
Senior Member
 
L'Avatar di Teo@Unix
 
Iscritto dal: Mar 2009
Messaggi: 753
In realtà, viene cambiato inizialmente, quando solo un thread è attivo, quindi si, dopo verrà solo letto.
In questo caso non dovrebbe essere necessaria la mutex.

La mia idea relativamente al progetto "di prova" di cui avevo mostrato alcune parti di codice nell'altro post, era di associare un thread ad ogni porta da scansionare, in modo da aumentare di molto la velocità di esecuzione. Il programmino l'ho realizzato per ora solo con due thread. Quello che si occupa della scansione soffre dei timeout della connect().

Perciò avevo pensato di provare definendo 4 thread.
Questi appena finiranno il lavoro con la loro porta andranno a prendersi la prossima e via dicendo fino all'ultima... per ora ho un pò di problemi con il buffer dei risultati ....
ora ho escluso un problema di uso errato di mutex.... resta da vedere come gestire al meglio thread del genere....

Se questa domanda ha un senso,
Come fareste idealmente per gestire più thread?

edit: a ok, non avevo letto la tua modifica, si si comunque mi stò studiando la faccenda....
Teo@Unix è offline   Rispondi citando il messaggio o parte di esso
Old 24-12-2009, 09:49   #5
cionci
Senior Member
 
L'Avatar di cionci
 
Iscritto dal: Apr 2000
Città: Vicino a Montecatini(Pistoia) Moto:Kawasaki Ninja ZX-9R Scudetti: 29
Messaggi: 53971
Non ha senso creare un thread per ogni porta da scansionare. Per diversi validi motivi:
- l'ip che scansioni molto probabilmente ti rileverà come una attacco DoS
- l'efficienza, dopo un certo numero di thread, si va a perdere
- il costo della creazione di un thread, seppur basso, è sempre un costo

Quindi io ti consiglio un tot di thread, magari aumentabile tramite l'interfaccia grafica (numero di porte scansionate contemporaneamente). Che so, da 4-5 a non più di 10.
Questo è detto "pool di thread". Questi thread non verranno creati e distrutti ad ogni scansione, ma verranno creati all'inizio e distrutti alla fine di tutte le scansioni.
Dovrai fornire al pool di thread i dati su cui lavorare. Col sistema dei segnali-slot è veramente semplice avere la notifica del completamente del lavoro, non c'è nemmeno bisogno di lavorare troppo di mutex o gestire la concorrenza sui dati.
Quando un thread avrà completato il suo lavoro emetterà un segnale (magari fornendo l'indice del thread che ha finito il lavoro o il suo puntatore) e si metterà in attesa su un QSemaphore.
Questo segnale sarà collegato ad uno slot che avrà il compito di:
- raccogliere il risultato
- fornire al thread un nuova porta su cui andare a lavorare
- riavviare il thread andando ad agire sul semaforo
Nel subclassing di QThread potresti aggiungere un metodo connect(const QString &IP, const int port) che fa le ultime due cose.
Quando crei e avvii il thread potrebbe automaticamente andarsi bloccare sul QSemaphore in attesa che il chiamante vada a fornirgli la porta su cui lavorare con connect (basta inizializzare il QSemaphore a 0).

Ultima modifica di cionci : 24-12-2009 alle 09:57.
cionci è offline   Rispondi citando il messaggio o parte di esso
Old 24-12-2009, 10:12   #6
Teo@Unix
Senior Member
 
L'Avatar di Teo@Unix
 
Iscritto dal: Mar 2009
Messaggi: 753
grazie chiarissimo,
dunque un semaforo mi fungerebbe da parcheggio...
perfetto avevo tentato di fare questa parte creandomi una routine nella classe MainWindow che gestiva proprio 4 thread...
così mi sembra semplice. Provo.
Teo@Unix è offline   Rispondi citando il messaggio o parte di esso
Old 25-12-2009, 22:10   #7
Teo@Unix
Senior Member
 
L'Avatar di Teo@Unix
 
Iscritto dal: Mar 2009
Messaggi: 753
Causa i consueti riti Natalizi non ho avuto molto tempo per provare,

ho però letto un pò la guida e ho visto che il "pool di threads" è una classe vera e propria, ho letto anche che, se il mio inglese non mi tradisce, occorre reimplementare QRunnable, nel senso che bisogna creare una classe derivata da QRunnable?

Quel che ho fatto è:

Nella classe MainWindow, dichiarata una classe derivata da QThreadPool.
Devo ora crearmi anche una classe QRunnable? E poi dichiarare in QThreadPool i miei thread QRunnable?
In questa metterei la connect() ecc...

spero di essermi spiegato bene...
Grazie.

Ultima modifica di Teo@Unix : 25-12-2009 alle 22:15.
Teo@Unix è offline   Rispondi citando il messaggio o parte di esso
Old 26-12-2009, 10:27   #8
cionci
Senior Member
 
L'Avatar di cionci
 
Iscritto dal: Apr 2000
Città: Vicino a Montecatini(Pistoia) Moto:Kawasaki Ninja ZX-9R Scudetti: 29
Messaggi: 53971
Ma non importa. Non sapevo nemmeno che esistesse
Per i tuoi scopi va più che bene un approccio più semplice. Almeno entri meglio nell'ottica dei thread e della loro gestione. Con QThreadPool, da quanto leggo, tutto il lavoro sui thread viene nascosto.
QThreadPool può essere comoda quando ci sono molti compiti diversi che possono essere svolti dai thread.
cionci è offline   Rispondi citando il messaggio o parte di esso
Old 26-12-2009, 10:53   #9
Teo@Unix
Senior Member
 
L'Avatar di Teo@Unix
 
Iscritto dal: Mar 2009
Messaggi: 753
Già, siccome nel mio programmino di prova il compito è sempre le stesso, niente QThreadPool....

A questo punto ciò che farei è:
1 una classe che contiene il metodo per la scansione [scanthread]
2 la solita classe MainWindow (mantegno quella della prima versione del programma) [MainWindow]
3 la classe struttura dati (anche questa è la medesima) [charon]

Ora, nel costruttore di MainWindow creo 4 elem. scanthread.
Quindi mi hai parlato di QSemaphore per gestirli...
però non saprei bene, anche dagli esempi proposti non ho trovato nulla di simile..... QSemaphore mi sembra molto simile a QMutex....

Alla run() dei thread potrei anche fargli ritornare il puntatore del thread stesso... ma non ho capito bene come utilizzarlo dopo per controllare i threads....

Thanks.
Teo@Unix è offline   Rispondi citando il messaggio o parte di esso
Old 26-12-2009, 11:02   #10
cionci
Senior Member
 
L'Avatar di cionci
 
Iscritto dal: Apr 2000
Città: Vicino a Montecatini(Pistoia) Moto:Kawasaki Ninja ZX-9R Scudetti: 29
Messaggi: 53971
Usando segnali e slot non hai bisogno della classe per condividere i dati. Infatti puoi recuperare i dati ed assegnarne di nuovi su cui lavorare direttamente della classe del tuo thread, perché il thread è fermo sul semaforo, quindi non ci sarai mai concorrenza.
cionci è offline   Rispondi citando il messaggio o parte di esso
Old 26-12-2009, 11:08   #11
Teo@Unix
Senior Member
 
L'Avatar di Teo@Unix
 
Iscritto dal: Mar 2009
Messaggi: 753
Quote:
Originariamente inviato da cionci Guarda i messaggi
perché il thread è fermo sul semaforo, quindi non ci sarai mai concorrenza.
sono un pò disorientato riguardo a questo punto però, cosa intendi per "fermo sul semaforo"?
Teo@Unix è offline   Rispondi citando il messaggio o parte di esso
Old 26-12-2009, 11:20   #12
cionci
Senior Member
 
L'Avatar di cionci
 
Iscritto dal: Apr 2000
Città: Vicino a Montecatini(Pistoia) Moto:Kawasaki Ninja ZX-9R Scudetti: 29
Messaggi: 53971
Quote:
Originariamente inviato da Teo@Unix Guarda i messaggi
sono un pò disorientato riguardo a questo punto però, cosa intendi per "fermo sul semaforo"?
Hai scritto tu "dunque un semaforo mi fungerebbe da parcheggio...", quindi credevo che avessi capito che l'esecuzione di un acquire su un semaforo rosso implica il blocco del thread. Il thread va risvegliato solo dopo che avrai inserito in nuovi dati su cui dovrà andare a lavorare eseguendo una release.
cionci è offline   Rispondi citando il messaggio o parte di esso
Old 26-12-2009, 11:33   #13
Teo@Unix
Senior Member
 
L'Avatar di Teo@Unix
 
Iscritto dal: Mar 2009
Messaggi: 753
forse ho capito,
la mia run del thread è corretto abbia questo prototipo:
ScanThread* ScanThread::run(QHostAddress host,unsigned int port,short timeout)
Teo@Unix è offline   Rispondi citando il messaggio o parte di esso
Old 26-12-2009, 11:36   #14
cionci
Senior Member
 
L'Avatar di cionci
 
Iscritto dal: Apr 2000
Città: Vicino a Montecatini(Pistoia) Moto:Kawasaki Ninja ZX-9R Scudetti: 29
Messaggi: 53971
Non si era detto che appena eseguivi la run il thread si andava a bloccare sul semaforo ?
I dati su cui lavorare glieli puoi fornire dopo, con un metodo della classe del thread (che andrà anche a risvegliarlo).
Creati il pool di thread in modo che siano tutti bloccati in attesa di riceve le informazioni per partire.
cionci è offline   Rispondi citando il messaggio o parte di esso
Old 26-12-2009, 13:12   #15
Teo@Unix
Senior Member
 
L'Avatar di Teo@Unix
 
Iscritto dal: Mar 2009
Messaggi: 753
...

dovrò passargli il semaforo però... umh?
ScanThread* run(QSemaphore*);

cioè dovrò per forza di cose passare il puntatore del semaforo al costruttore del thread. giusto?

Nel momento che il thread avrà finito farà sem.acquire() bloccandosi finche in mainwindow non eseguo sem.release().... ma posso utilizzare i metodi del thread per passargli i dati se esso è bloccato sul semaforo....

..scusa, ma stò faticando con questa parte....
Teo@Unix è offline   Rispondi citando il messaggio o parte di esso
Old 26-12-2009, 14:08   #16
cionci
Senior Member
 
L'Avatar di cionci
 
Iscritto dal: Apr 2000
Città: Vicino a Montecatini(Pistoia) Moto:Kawasaki Ninja ZX-9R Scudetti: 29
Messaggi: 53971
Non importa, il semaphoro lo puoi creare come variabile membro del thread.
Poi dopo andrai a chiamare, ad esempio:

thread->connect(......):

In cui passerai i dati su cui il thread andrà a lavorare.
In fondo alla conncect chiamerai la release sul semaforo.
cionci è offline   Rispondi citando il messaggio o parte di esso
Old 26-12-2009, 16:59   #17
Teo@Unix
Senior Member
 
L'Avatar di Teo@Unix
 
Iscritto dal: Mar 2009
Messaggi: 753
Potrebbe essere una valida implementazione dell classe thread?
Ti sembra giusto l'uso dei semafori? (non ho provato nulla)

Codice:
#ifndef SCANTHREAD_H
#define SCANTHREAD_H

#include <QThread>
#include <QTcpSocket>
#include <QHostAddress>
#include <QString>
#include <QSemaphore>

class ScanThread : public QThread
{
    Q_OBJECT
private:
    //Dati
    unsigned int ThisPort;
    short int ThisTimeout;
    QString ThisHost;
    QTcpSocket socket;
    QString buffer;
    QSemaphore semaphore;
    //Metodi
    void ResolveService(unsigned int);
    
public:
    //Metodi pubblici
    ScanThread();
    void run();
    QString get_buffer();
public slots:
    void AwakeningProcess(unsigned int,QString,short);
};

#endif // SCANTHREAD_H

Codice:
#include "scanthread.h"

ScanThread::ScanThread()
{
    semaphore(0);
}

void ScanThread::run()
{
    while(semaphore.acquire(1))
    {
        socket.connectToHost(ThisHost,Thisport);
        if(socket.waitForConnected(ThisTimeout*1000))
        {
            buffer.append(tr("Rilevata porta %1 aperta - ").arg(ThisPort));
            ResolveService(port);
        }
    }
}

void ScanThread::ResolveService(unsigned int port)
{
    struct servent* service;
    if((service = getservbyport(htons(port),"tcp")) == NULL)
        buffer.append(tr("Impossibile risalire al servizio in esecuzione sulla porta\n"));
    else
        buffer.append(tr("%1 in esecuzione\n").arg(service->s_name));    
}

void ScanThread::AwakeningProcess(unsigned int port,QString Host,short timeout)
{
    ThisPort = port;
    ThisTimeout = timeout;
    ThisHost = Host;
    semaphore.release(1);
}
l'ultima funzione qui sopra dovrebbe passargli i parametri e svegliare il thread... mmmm che ne pensi?

Ultima modifica di Teo@Unix : 26-12-2009 alle 17:01.
Teo@Unix è offline   Rispondi citando il messaggio o parte di esso
Old 26-12-2009, 17:19   #18
cionci
Senior Member
 
L'Avatar di cionci
 
Iscritto dal: Apr 2000
Città: Vicino a Montecatini(Pistoia) Moto:Kawasaki Ninja ZX-9R Scudetti: 29
Messaggi: 53971
Va benissimo
Ottima scelta del while per il ciclo, ma acquire non torna alcun valore, è void.
Quindi dovresti mettere la acquire all'interno del ciclo e fare un while(1).

L'unico problema è questo:

Codice:
ScanThread::ScanThread()
{
    semaphore(0);
}
Non può funzionare così, devi utilizzare una lista di inizializzazione In quanto in quel punto lì, semaphore è già stato inizializzato. Comunque in questo caso non serve perché il QSemaphore viene già inizializzato a zero.

Ultima modifica di cionci : 26-12-2009 alle 17:21.
cionci è offline   Rispondi citando il messaggio o parte di esso
Old 26-12-2009, 17:59   #19
Teo@Unix
Senior Member
 
L'Avatar di Teo@Unix
 
Iscritto dal: Mar 2009
Messaggi: 753
Ok, ho modificato opportunamente.

Ora, questione gestione dei threads.........

Lo faccio nella classe mainwindow naturalmente.... siccome non posso piantarci un ciclo che crei attese se nò sarei punto capo...... avevo pensato di avviarne inizialmente uno, praticamente nello slot associato al pulsante start metterei:
thread0->AwakeningProcess(CurPort,Host,timeout);
va a chiamare il metodo del mio thread e fa eseguire al thread un nuovo ciclo con i nuovi dati.....
se ci sono più di una porta obiettivo avvio gli altri... il tutto sarebbe così:
(anche se non mi pare molto elegante)

Codice:
     CurPort = Sport;
    thread0->AwakeningProcess(CurPort,Host,timeout);
    if(CurPort==Eport) {}//Ho finito...
    CurPort++;
    thread1->AwakeningProcess(CurPort,Host,timeout);
    if(CurPort==Eport) {}//Ho finito...
    CurPort++;
    thread2->AwakeningProcess(CurPort,Host,timeout);
    if(CurPort==Eport) {}//Ho finito...
    CurPort++;
    thread3->AwakeningProcess(CurPort,Host,timeout);

Nel caso le porte sono più di 4....
avevo pensato di collegare il segnale finished() per ogni thread
con la funzione:
Codice:
void MainWindow::NextThread(ScanThread* thread)
{
    ScanThread* CurrentThread = thread;
    CurrentThread->AwakeningProcess(++CurPort,Host,timeout);
}
che incrementa la porta corrente e riavvia il thread per una nuova scansione, in questo modo i thread dovrebbeo essere sempre impegnati.
IL problema che ho incontrato è che nella funzione connect() non posso pasare un argomento allo slot, vuole solo i tipi....
Codice:
 connect(thread0,SIGNAL(sleep()),this,SLOT(NextThread(ScanThread*)))
quindi come passo il puntatore del thread disponibile?

Hai idee migliori per gestire i threads?

Grazie molte.

Ultima modifica di Teo@Unix : 26-12-2009 alle 18:21.
Teo@Unix è offline   Rispondi citando il messaggio o parte di esso
Old 27-12-2009, 09:22   #20
cionci
Senior Member
 
L'Avatar di cionci
 
Iscritto dal: Apr 2000
Città: Vicino a Montecatini(Pistoia) Moto:Kawasaki Ninja ZX-9R Scudetti: 29
Messaggi: 53971
Codice:
void MainWindow::NextThread(ScanThread* thread)
{
    ScanThread* CurrentThread = thread;
    //qui devi anche recuperare il risultato
    CurrentThread->AwakeningProcess(++CurPort,Host,timeout);
}
Inoltre devi emettere un segnale per risolvere il problema
http://doc.trolltech.com/4.5/signals...-small-example
Crea un signal nella classe del thread che si chiama ad esempio workDone(ScanThread* thread). Lo devi collegare allo slot NextThread tramite la connect.
Dopo che hai emesso il segnale devi fare la acquire sul semaforo.
cionci è offline   Rispondi citando il messaggio o parte di esso
 Rispondi


Lenovo IdeaPad Slim 3: un notebook Snapdragon X economico Lenovo IdeaPad Slim 3: un notebook Snapdragon X ...
Recensione OnePlus Watch 3 43mm: lo smartwatch che mancava per i polsi più piccoli Recensione OnePlus Watch 3 43mm: lo smartwatch c...
BOOX Note Air4 C è uno spettacolo: il tablet E Ink con Android per lettura e scrittura BOOX Note Air4 C è uno spettacolo: il tab...
Recensione Sony Xperia 1 VII: lo smartphone per gli appassionati di fotografia Recensione Sony Xperia 1 VII: lo smartphone per ...
Attenti a Poco F7: può essere il best buy del 2025. Recensione Attenti a Poco F7: può essere il best buy...
La NASA e IBM hanno annunciato il nuovo ...
Nikon ha annunciato l'obiettivo per foto...
Il Trump Phone non esiste? Per ora ci so...
Le canzoni di Spotify arrivano nelle Sto...
Il governo cinese svela i sussidi erogat...
Vision Discovery Edition: ecco il primo ...
Il robot lavapavimenti geniale: non lo d...
Il MIT gela l'entusiasmo sull'AI: 95% de...
Anche la nuova Renault Twingo avrà...
Back to School 2025: sconti pazzi su tec...
Tutte le offerte Apple da non perdere: A...
Google lancia Gemini for Government: una...
Xiaomi lancia sconti imperdibili: ventil...
Tesla sotto indagine per non aver segnal...
WhatsApp Beta iOS: semplificata la segna...
Chromium
GPU-Z
OCCT
LibreOffice Portable
Opera One Portable
Opera One 106
CCleaner Portable
CCleaner Standard
Cpu-Z
Driver NVIDIA GeForce 546.65 WHQL
SmartFTP
Trillian
Google Chrome Portable
Google Chrome 120
VirtualBox
Tutti gli articoli Tutte le news Tutti i download

Strumenti

Regole
Non Puoi aprire nuove discussioni
Non Puoi rispondere ai messaggi
Non Puoi allegare file
Non Puoi modificare i tuoi messaggi

Il codice vB è On
Le Faccine sono On
Il codice [IMG] è On
Il codice HTML è Off
Vai al Forum


Tutti gli orari sono GMT +1. Ora sono le: 04:13.


Powered by vBulletin® Version 3.6.4
Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
Served by www3v