Newsgroup: it.comp.programmare.win32
Titolo: Threads, messaggi e concorrenza

Spero possiate aiutarmi a risovere questa situazione.
Il thread A esegue la window procedure della sua window, gestendone i
messaggi.
In risposta al messaggio M1 deve lavorare su una risorsa R (una lista di
puntatori ad oggetti).
Arriva un messaggio M1 ed il thread inizia a gestirlo (l'operazione puň
essere lunga e richiede che la risorsa R non venga "sporcata").
Il thread B esegue una SendMessage() verso la window del thread A, spedendo
un messaggio M2 che modifica la risorsa R.
Come faccio a "serializzare" la gestione di M1 ed M2?
La risorsa R viene acceduta previa acquisizione di un mutex sia nella
gestione di M1 che di M2, ma essendo sempre A a gestire i messaggi, la
seconda richiesta del mutex viene (giustamente, rischio di deadlock) fatta
passare.
Una possibile soluzione potrebbe essere mettere la SendMessage(M2) dopo un
accesso al mutex da parte del thread B.
Che ne pensate? Suggerimenti?
Grazie dell'aiuto.
Luigi


Una SendMessage tra thread diversi (è il caso di M2) passa comunque per il 
loop dei messaggi e viene quindi eseguita dopo che è stato processato M1.
L'unico inconveniente è che anche il thread B rimane bloccato.
Potrebbe verificarsi un deadlock se A cerca di accedere a risorse che sono 
bloccate da B o prova a fare una SendMessage verso una delle window del 
thread B.
L'idea di far acquisire il mutex prima di inviare M2 può solo peggiorare la 
situazione (rischia di bloccare M1).
-- 
Valter Minute
min...@inwind.it
 (the reply address of this message is invalid)

 loop dei messaggi e viene quindi eseguita dopo che è stato processato M1.
Se questo fosse vero sempre il problema non si porrebbe, in quanto le
gestioni dei messaggi sarebbero di per se serializzate senza rischi di
interferenza sulla risorsa R. Ho verificato a debug che durante un WM_PAINT
una SendMessage() con un messaggio user defined vien gestita immediatamente.
A- inizia la gestione del wm_paint
A- lock del mutex
A- inizio lavoro sulla risorsa R
B- SendMessage(user defined message)
A- gestisce il messaggio user defined mentre B è sospeso
A- lock del mutex (passa di sicuro, è lo stesso thread)
A- modifica R
B- sbloccato, prosegue
A- prosegue la gestione del wm_paint, ma R è stata modificata!
Luigi

: 

dall'help relativo a SendMessage:
"If the specified window was created by the calling thread, the window 
procedure is called immediately as a subroutine. If the specified window 
was created by a different thread, the system switches to that thread and 
calls the appropriate window procedure. Messages sent between threads are 
processed only when the receiving thread executes message retrieval code. 
The sending thread is blocked until the receiving thread processes the 
message. However, the sending thread will process messages from its queue 
while waiting for its message to be processed. To prevent this, use 
SendMessageTimeout with SMTO_BLOCK set."
Credo che la chiave di tutto sia quel "message retrieval code" con cui si 
intendono Get/PeekMessage ma anche Message/DialogBox.
Sei sicuro che la finestra appartenga al thread A? Il funzionamento che 
esponi (SendMessage "nidificate" e doppio accesso al mutex) sarebbe 
spiegabile se tutto avvenisse dentro lo stesso thread.
Puoi controllare richiamando GetCurrentThreadId e stampandone il valore con 
OutputDebugString (message box e simili riattivano il processing dei 
messaggi).
WM_PAINT è un messaggio a bassa priorità, ma questo dovrebbe influenzare 
solo l'ordine con cui viene messo in coda, non il fatto che possa essere 
interrotto, a meno che una delle funzioni "peculiari" di WM_PAINT 
(Begin/EndPaint) vada a sbloccare la coda dei messaggi (ma questo non è 
documentato, AFAIK).


Spero possiate aiutarmi a risovere questa situazione.
Hai provato PostMessage()  ?

 writes:
LG> Spero possiate aiutarmi a risovere questa situazione.
LG> Il thread A esegue la window procedure della sua window, gestendone i
LG> messaggi.
LG> In risposta al messaggio M1 deve lavorare su una risorsa R (una lista di
LG> puntatori ad oggetti).
Se invece di A usi A1, ulteriore thread dello stesso task, per gestire R ?
A passa  ad A1  una richiesta  di elaborazione di  R e  tale richiesta
viene  messa   in  una  coda   (ti  rimane  da  gestire   un  problema
lettori/scrittori  la cui  soluzione  è  nota) da  cui  A1 preleva  le
richieste, mettiamo con  politica FUIFO. Se la coda  è vuota A1 dorme,
qui un semaforo ci cade come il cacio sui maccheroni.
Più o meno A1 è una cosa del genere
	A1:
		Se il semaforo non è segnalato
			wait sul semaforo
		Altrimenti
			decrementa il semaforo
			preleva il primo messaggio dalla coda
			elabora il messaggio
			loop su A1
 
B manda il messaggio M2 ad A,  A accoda una richiesta sulla coda di A1
e termina  la gestione del messaggio  M2. A1 non  gestirà la richiesta
generata da M2 fintanto che non avrà terminato la precedente.
Se è necessario che B  attenda l'elaborazione del messaggio puoi usare
un'evento  per segnalare  da A1  a B  il completamento  dell'opera, ma
occhio che qui si possono presentare i già citati deadlock.
--
Gian Uberto| main(){printf(&unix["\021%six\012\0"],(unix)["have"]+"fun"-0x60);}
Lauri      |                        David Korn, 1987 ioccc best one liner 
(aka saint)|-------------------------------------------------------------------
em@ail: 
sa...@eng.it
 ( vedere X-nospam nello header - see X-nospam in header )

> loop dei messaggi e viene quindi eseguita dopo che è stato processato M1.
LG> Se questo fosse vero sempre il problema non si porrebbe, in quanto le
LG> gestioni dei messaggi sarebbero di per se serializzate senza rischi di
LG> interferenza sulla risorsa R. Ho verificato a debug che durante un WM_PAINT
LG> una SendMessage() con un messaggio user defined vien gestita immediatamente.
LG> A- inizia la gestione del wm_paint
LG> A- lock del mutex
LG> A- inizio lavoro sulla risorsa R
LG> B- SendMessage(user defined message)
LG> A- gestisce il messaggio user defined mentre B è sospeso
Grande, tutto il contrario di  quello che dice la documentazione ed il
Richter  :)!  La  spiegazione  è  che  in mezzo  ci  deve  essere  una
<Get|Peek> message nascosta :)
Nell'altro post  avevo dato una soluzione  che è da  scegliersi se non
sei  in grado di  "insegnare l'educazione  a B".   Altrimenti dovrebbe
esserci un'oggetto di sincronizzazione  condiviso (semaforo) tra A e B
e ciascuno  dei due  thread deve attendere  che la risorsa  sia libera
prima di  provare a  prenderla. Qundi  A prima di  iniziare a  fare la
WM_PAINT pone a 0  il semaforo se e solo se lo  trova ad 1, altrimenti
attende - idem  B, che prima di inviare inviare il  messaggio pone a 0
il semaforo se e solo se  questo è a 1, altrimenti attende. Ovviamente
ciascuno ripristina il messaggio appena ha finito.


 intendono Get/PeekMessage ma anche Message/DialogBox.
Credo di averlo trovato! Nel codice di gestione del messaggio viene usata
una macro di debug che esegue una SendMessage() verso un'applicazione per
visualizzare dei messaggi. Ho provato a commentarla ed il problema non si
verifica. Quindi mi sembra di capire che una SendMessage() é "message
retrieval code", roba da evitare se si vuole essere certi che la gestione di
un messaggio non sia "interrompibile".
Ringrazio tutti, in particolare Valter Minute, per il sostegno e l'aiuto.
Vostro debitore,
Luigi