Le macro di gestione dei thread di CLB_thread

In quest’ultima parte dell’articolo introdurremo un insieme di macro, appartenenti a CLB_lang, che semplificano la gestione ed attivazione dei thread associati alle classi CLB_thread. Abbiamo già osservato che le classi CLB_thread non espongono direttamente la dichiarazione delle funzioni thread eseguite, ma solo un insieme di funzioni e macro, valide per qualunque classe derivata, che ne permettono la gestione in termini di lancio, sospensione, interruzione e stato di attività. Vediamo con un esempio reale, scritto all’interno di Colibri: la classe  THREAD_calc_dither.

THREAD_calc_dither è una classe che riceve in ingresso un file da retinare ed altri parametri utilizzati per la retinatura, eseguendo  internamente un thread.  La procedura chiamante, a fine esecuzione potrà richiedere il file retinato attraverso la funzione Get_dithered_map(). . Non discutiamo del risultato del procedimento,  ma solo sul modo in cui i parametri sono passati alla classe THREAD_calc_dither e come internamente vengono usati.

Di seguito la dichiarazione dell classe:

class AFX_EXT_CLASS THREAD_calc_dither   : public CLB_thread
	{
	public:
	THREAD_calc_dither(void);
	~THREAD_calc_dither(void);

	virtual bool Start();

	IMG_FBUF *Get_dithered_map();	

	__use_private_struct
};

Come si osserva, la classe espone solo due funzioni:

  • Start() usata per lanciare il thread interno
  • Get_dithered_map() per estrarre il risultato a fine processo

La Start è la riscrittura della classe virtuale CLB_Thread, che, come abbiamo scritto è necessario riscrivere per le classi derivate;

La classe THREAD_calc_dither è usata in una funzione che esegue la trasformazione di un insieme di canali graytone in canali retinati:

	bool CREATE_DITHERING(CLASS_STR)
	{
		__cursor_wait	// visualizza il cursore di waiting

		int n=_$str->img->GetChannelList()->Num();
		DOC_AREA *ar=$obj->GetSize();

		
		// usa le curve della variante attiva;
		//
		if (_$str->use_curve) {
			COLORWAY *cwy=_$str->img->GetColorwayProject()->GetColorway();
			cwy->GetDensityCurves(_$str->_DENSITY);
		}

                _$str->threads= new CLB_thread_list; 
		for (int i=0;i<n;i++) {

			__thread_new(THREAD_calc_dither);

			__thr_push_p(_$str->img->GetChannelList()->GetChannel(i))	// canale 
			__thr_push_p(_$str->dth[i])									// dithering da usare
			__thr_push_p(&ar->dx)										// dimensioni mappa generata
			__thr_push_p(&ar->dy)
			if (_$str->use_curve)
				__thr_push_p(_$str->_DENSITY[i])							// curva di correzione densità
			else __thr_push_p(0);

			_$str->threads->Add(_thr);
		}
		_$str->threads->UseDisplayProgressWindow(__translate("Create Screens channels"),
							__translate(" Wait: the program is building dithered channels.."));
		return _$str->threads->Start();
	}

Prima osservazione: Come si può intuire dalla lettura del codice, ciascun canale graytone è retinatato da un thread; per fare questo si allocano  tanti thread quanti sono i canali , aggiungendoli come thread figli ad un gestore della lista: CLB_thread_list :

 _$str->threads= new CLB_thread_list;

CLB_thread_list ha il compito di generare un thread che rimane in attesa che tutti i thread figli siano correttamente terminati.

Il ciclo di for(..) che segue genera ed assegna i parametri a ciascun THREAD_calc_dither, aggiungendolo al CLB_thread_list

for (int i=0;i<n;i++) {

			__thread_new(THREAD_calc_dither);

			__thr_push_p(_$str->img->GetChannelList()->GetChannel(i))	// canale 
			__thr_push_p(_$str->dth[i])									// dithering da usare
			__thr_push_p(&ar->dx)										// dimensioni mappa generata
			__thr_push_p(&ar->dy)
			if (_$str->use_curve)
				__thr_push_p(_$str->_DENSITY[i])							// curva di correzione densità
			else __thr_push_p(0);

			_$str->threads->Add(_thr);
		}

Per farlo utilizza due macro di CLB_lang;

_thread_new :

genera un’istanza del tipo passato (THREAD_calc_dither).  il nome dell’istanza è, convenzionalmente _thr  per semplificare la scrittura del codice successivo.

__thr_push_p :

inserisce sequenzialmente i parametri utilizzati dalla classe per l’esecuzione dei calcoli.  argomento della macro è  sempre un puntatore; la macro è richiamata tante volte quanti sono gli argomenti da passare alla THREAD_calc_dither.

Quindi l’istanza _thread viene aggiunta alla lista di esecuzione.

..
_$str->threads->Add(_thr);
..

A terminazione del  ciclo di costruzione, viene chiamata una funzione di CLB_thread_list che inizializza una finestra di visualizzazione dello stato di esecuzione dei thread; vengono assegnate due stringhe di visualizzazione

_$str->threads->UseDisplayProgressWindow(__translate("Create Screens channels"),
							__translate(" Wait: the program is building dithered channels.."));

La finestra (modale) verrà visualizzata durante l’esecuzione del/dei thread

return _$str->threads->Start();

Seconda osservazione: CLB_thread_list ::Start() manda in esecuzione tutti i thread figli  chiamandone la funzione Start(), quindi lancia un thread interno di attesa terminazione.

Pages: 1 2 3 4 5 6 7 8
Skip to toolbar