Comunicação Full Duplex sem threads

Indo direito ao ponto: Meu professor pediu que eu fizesse um chat com comunicação full duplex via porta serial, no windows.
A priori, era apenas uma comunicação bidirecional, foi até de boas pra fazer, mas agora eu preciso receber e enviar “ao mesmo tempo”. Meu conhecimento é um pouco abaixo de intermediário qndo se trata de C/C++. Minha praia mesmo é Java, onde tenho conhecimento avançado.
Tentei pensar no que eu faria se estivesse fazendo esse programa em Java: usaria threads. Acontece que o professor não ministrou esse assunto na matéria dele, o que me faz pensar que deve haver outra maneira de fazer.
E é este o meu problema: gostaria de saber se tem como fazer a comunicação full duplex sem usar threads.
Obs.: A ideia é fazer isso com C estruturado, sem OO, mas caso precise usar algo de C++, não tem problema, a não ser que eu possa implementar a funcionalidade desse algo de maneira simples, em C.

O arquivo main.c é este: https://github.com/wyalves/FullDuplexSerialComm/blob/master/main.c
Por enquanto, eu tenho que escolher quem será o receptor e o emissor pelo código.

Cara, me desculpe a ignorância, mas eu sinceramente não consigo ver nenhuma maneira de fazer duas tarefas (ler e escrever) ao mesmo tempo sem utilizar necessariamente mais de uma thread ou processo.

Algo que eu vejo como uma possível solução procedural com apenas uma thread é:

  1. Escreve alguma coisa
  2. Fica parado esperando alguém escrever algo
  3. Repete

Ou então o contrário, primeiro espera alguém falar algo, depois escreve e volta a esperar.

Mesmo que haja alguma maneira de fazer “hooks” com o sistema operacional para te avisar quando acontecer algum evento (escrita no buffer da porta, por exemplo), o sistema vai chamar teus métodos a partir de outras threads.

Como dizia meu avô: quem chupa cana não assobia kkkkk

KKKK foi oq imaginei mesmo. Lá vou eu estudar threads em C :sweat: . Obrigado!

O fato de poder receber e enviar ao mesmo tempo, não implica que você tem que poder ler e escrever no seu aplicativo no mesmo instante. Implica que você não precisa esperar liberar o canal pra poder escrever.

Você pode fazer com threads nada impede, só que isso não tem a ver com ser full duplex o canal de comunicação.

Normalmente você faz algo do tipo com polling. No caso do linux:
https://linux.die.net/man/2/select
https://linux.die.net/man/2/poll

No Windows:

1 curtida

Tens razão, não me liguei nesse ponto. Quando ele disse “preciso receber e enviar ao mesmo tempo”, imaginei algo como um “chat”, algo com real time de forma eficiente.

Polling é uma alternativa para fazer single-threaded porque não bloqueia a thread eternamente, mas tem uma balança de eficiência x velocidade. Se o timeout é muito pequeno, vai ficar bem rápido, mas ineficiente (se mensagens demoram mais a chegar, muitas instruções são executadas em vão). Se o timeout é grande, fica mais eficiente (menos instruções executadas em vão), mas perde o quesito “real time”, fica mais lento. Num dispositivo embarcado que usa uma bateria, por exemplo, ineficiência poderia drenar a bateria um pouco mais rápido.

Outra situação um pouco inconveniente é o seguinte: se, por exemplo, as mensagens que chegam (ou que saem) são muito grandes, é necessário criar uma espécie de protocolo para balancear o trabalho da thread entre ler e escrever.

Tudo é relativo, depende muito do caso. Polling é sim uma alternativa válida, mas na minha humilde opinião, com multi-threading (caso seja uma opção) pode ser eficiente e rápido ao mesmo tempo.

O que achas? @Kronal

Dai você pode usar uma thread pra comunicação com o seu dispositivo serial, com tempo infinito e chama a rotina especifica quando relevante. Acho que é uma boa, e separa o código legal, e fica como se fosse orientado a eventos.

Talvez nem seja necessário usar thread pra escrita, ela poderia ser executada na thread principal mesmo caso não for necessário esperar se o socket/dispositivo pode ser escrito. Manda e esquece. Talvez só a leitura precisaria ficar em loop aguardando.

Bom, salvo o caso quando tu usa uma biblioteca pra esconder isso, mesmo usando várias threads você vai ter que ou fazer polling pra ver se recebeu algo ou fazer leitura/escrita bloqueante, com uma thread pra entrada e outra pra saída. Acaba dando na mesma, e talvez até usar 2 threads consuma mais recursos. Só testando sinceramente se existir esse tipo de requisito.

Verdade. Acho que a resposta, como sempre, é “depende” hehe

A abstração de usar threads com bloqueio facilita, mas o overhead da criação/manutenção (troca de contexto) delas pode acabar sendo prejudicial em certas situações (num single core, com muitas mensagens pequenas entrando e saindo, por exemplo).

Vlw gente, vcs tão ajudando mto! kkk