Newsgroup: it.comp.programmare
Titolo: Programmazione a eventi ma anche no

Ciao,
ho un minimo di confusione dal momento che sto programmando 
contemporaneamente su architetture diverse con linguaggi diversi.
Dunque, vediamo di chiarire almeno un punto dei tanti:
Linguaggio: C++
IDE: Visual C++ 2010 Express
Applicazione: Win32 Console
ho bisogno di effettuare determinate operazioni a intervalli regolari o 
all'attivazione di un evento (es. ricezione seriale).
Bene, mi sono scritto le mie classi con i vari metodi.
Ora sto provando una cosa semplice, richiamare con un timer una funzione.
Nel main creo il timer e indico una mia funzione di callback:
UINT_PTR pTimer = SetTimer(NULL, 1, 1000, TimerTick);
definita come segue:
void CALLBACK TimerTick(HWND hwnd, UINT uMsg, UINT_PTR idEvent, DWORD 
dwTime) {
	printf ("OK\n");
}
Ora, in un programma a eventi io non devo preoccuparmi del "flusso" del 
programma in quanto vengono servite le varie procedure a mano a mano che 
sono richieste.
Ma qui? Non capisco come fare per "aspettare" che i vari eventi accadano.
Comunque, per test ho provato a mettere istruzioni bloccanti come 
while(1); o system("PAUSE"); senza che la mia callback venisse chiamata.
In conclusione, vi domando due cose in particolare:
1) nell'esempio in questione come fare per attendere "senza fare niente" 
che vengano chiamati gli eventi?
2) in generale, come faccio a realizzare un programma C++ basato sugli 
eventi e non sul flusso continuo del programma?
Grazie!
Marco

 eventi e non sul flusso continuo del programma?
In generale, aspettare che un evento accada significa effettuare una 
chiamata di sistema che ritorna solo quando una certa condizione si 
verifica. Per evitare attese indefinite, alcune chiamate di sistema 
hanno un parametro di timeout oppure falliscono dopo un timeout 
impostato precedentemente.
-- 
Carlo Milanesi
http://digilander.libero.it/carlmila

 impostato precedentemente.
Mumble, non mi torna.
Provo a spiegarmi: in sintesi vorrei ottenere lo stesso comportamento 
che ho con le GUI ma in modalità console.
Ovvero:
1) all'avvio il programma inizializza quello che deve inizializzare e 
aspetta
2) allo scadere dei timer esegue le funzioni associate
3) alla ricezione dei dati sulla seriale elabora ed esegue quanto necessario
Se dovessi implementarlo con una GUI non ci sarebbero problemi: non 
faccio altro che inserire il punto 1) al caricamento dell'interfaccia e 
i punti 2) e 3) finirebbero direttamente nelle funzioni legate agli eventi.
Se dovessi implementarlo in un microcontroller (quindi senza GUI) 
metterei il punto 1) all'inizio del codice seguito da un for(;;) {} come 
ciclo infinito e i punti 2) e 3) finirebbero nelle ISR dei timer e della 
seriale.
Ma nel caso di programmazione C++ console su pc non posso fare un ciclo 
infinito perché mi succhierebbe tutta la CPU e nemmeno inserire ritardi 
avrebbe molto senso.
Quindi: come si fa a ottenere lo stesso comportamento a eventi di una 
GUI *senza* che sia necessario averla?
Non credo che sia una cosa impossibile da fare, la programmazione a 
eventi (interrupt) non è necessariamente legata all'interazione con 
l'utente.
Grazie!
Marco

 Per i programmi Console esistono altri tipi di timer
Dimenticavo: potresti darmi qualche hint così vado a informarmi?
Grazie ancora
Marco

 non Console.
Una cosa del genere la ritieni quindi inopportuna?
VOID CALLBACK TimerProc(HWND hWnd, UINT nMsg, UINT nIDEvent, DWORD dwTime) {
	// to do
}
int _tmain(int argc, _TCHAR* argv[]) {
	MSG Msg;
	UINT TimerId = SetTimer(NULL, 0, 250, &TimerProc);
	bool bRet;
	while((bRet = GetMessage(&Msg, NULL, 0, 0)) != 0) {
		if (bRet == -1)	{
			// errore
		} else {
			DispatchMessage(&Msg);
		}
	}
Ciao!
Marco

 l'utente.
Questo newsgroup si riferisce a tecniche di programmazione in generale, 
cioe' indipendenti dal linguaggio e indipendenti dalla piattaforma.
Per sapere come fare certe cose specificamente in ambiente Windows, 
rivolgiti a it.comp.programmare.win32.
Comunque, in generale, la programmazione a eventi usando un sistema di 
programmazione che non la supporta nativamente si fa chiamando una 
funzione di sistema che ritorna solo quando forse e' successo un evento 
interessante.
Questo si puo' ottenere per esempio con GetMessage in ambiente GUI di 
Windows, che ritorna quando e' arrivato un messaggio, o con ReadFile che 
ritorna quando viene letto un dato.
Il tuo problema e' come fare ad attendere contemporaneamente due eventi 
di natura diversa, per esempio un messaggio GUI o un dato da un file, 
risvegliando il thread quando arriva il primo dei due.
Se uno dei due eventi e' il fatto che e' trascorso un po' di tempo, 
talvolta basta impostare un limite temporale (timeout), oltre il quale 
l'attesa finisce. A questo punto si deve verificare se l'attesa e' 
finita perche' e' arrivato un dato o perche' e' scaduto il tempo.
Nel primo caso, si elabora il dato e ritorna in attesa per il tempo 
rimanente allo scadere dell'intervallo. Nel secondo caso, non si elabora 
in quanto non e' arrivato, si esegue l'attivita' periodica, e si ritorna 
in attesa per un intervallo pieno.
Alternativamente, se tutti gli eventi possono essere attesi 
contemporaneamente con la stessa chiamata di funzione, si usa tale 
chiamta (vedi "WaitForMultipleObjects" per Windows e "select" per POSIX).
Se neanche questa soluzione e' fattibile, suppongo si debba ricorrere 
alla programmazione multi-threaded.
Una possibilita' e' basarsi sulla GUI e sulla GetMessage. Il thread 
principale attende messaggi con la GetMessage, mentre uno o piu' thread 
secondari attendono uno o piu' eventi di altro tipo. Quando un thread 
secondario viene risvegliato dal verificarsi di un evento, invia un 
messaggio di Windows al thread principale, e torna in attesa.
Un'altra possibilita' e' basarsi sulle funzioni kernel di attesa 
("WaitForMultipleObjects" o "select"). Il thread principale attende vari 
tipi di eventi tra cui un oggetto di sincronizzazione (che in ambiente 
Windows si chiama appunto "Event"), mentre uno o piu' thread secondari 
attendono uno o piu' eventi di altro tipo. Quando un thread secondario 
viene risvegliato dal verificarsi di un evento, imposta l'oggetto Event, 
il che risveglia il thread principale, e torna in attesa.
I timer di Windows che non si basano su finestre e messaggi GUI sono i 
"Waitable Timer Objects": 
http://msdn.microsoft.com/en-us/library/ms687012%28VS.85%29.aspx


 
http://msdn.microsoft.com/en-us/library/ms687012%28VS.85%29.aspx
Grazie per la spiegazione e del tempo che hai dedicato a scrivere il post.
Buona domenica!
Marco