Puisqu'il n'y avait pas d'API de type Suspend Thread sous Linux, essayez de suspendre / reprendre le thread avec mutex.
Pour le moment, je l'ai implémenté deux fois, mais j'ai souligné que je n'ai pas beaucoup de connaissances sur l'implémentation de l'API OS, donc je l'ai mangé deux fois, donc j'en suis fou, alors je me demande si c'est la troisième fois pour être honnête ou s'il y en a deux.
Points de @drab
Points à souligner par @ angel_p_57
Lors de la mise en œuvre du traitement des messages ou quelque chose comme ça Lorsque vous souhaitez traiter en continu les messages de la file d'attente après les avoir mis dans la file d'attente (en bref, un traitement asynchrone tel que l'envoi vers le nord-ouest).
Je veux suspendre le fil à un moment donné, car c'est un gaspillage de ressources qui font une boucle inutile quand il n'y a pas de message. Bref, je veux attendre l'événement.
Fait remarquer: l'utilisation de pthread_cond_wait dans le code qui fait quelque chose avec un événement de frappe est susceptible d'être terminée Ce que je veux faire: je veux attendre un événement.
En dehors.
~~ Un mémo pour mettre en pause l'utilisation de Mutex dans un tel cas. ~~
~~ ** 2017/04/17 Je l'ai écrit avec la méthode de mise en œuvre correcte selon le sujet signalé. (Voir le bas de l'article) ** ~~ ** 2017/04/21 Corrigé à nouveau **
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>
#include <pthread.h>
#include <unistd.h>
#include <stdarg.h>
#include<stdint.h>
#include<assert.h>
//Mettez une chaîne sur la console
int consoleWrite(const char *fmt, ...)
{
va_list list;
va_start(list, fmt);
int writed = vprintf(fmt, list);
fflush(stdout);
va_end(list);
return writed;
}
//Accepter les chaînes du clavier
size_t input(char *buf, size_t bufLen)
{
#define GabageBufSize 0x100
uint8_t bin[GabageBufSize];
char *savePtr = NULL;
char *token = NULL;
static_assert(sizeof(bin) == GabageBufSize, "Gabage buffer size not 255");
fgets(buf, bufLen, stdin);
token = strchr(buf, '\n');
if (token != NULL)
{
*token = '\0';
}
else
{
buf[bufLen - 1] = '\0';
while (token == NULL)
{
fgets(bin, GabageBufSize, stdin);
token = strchr(bin, '\n');
if (token != NULL)
{
break;
}
}
}
return strlen(buf);
}
//C'est une mauvaise implémentation
void suspend(pthread_mutex_t* lock)
{
pthread_mutex_trylock(lock);
//S'il n'a jamais été verrouillé, il sera verrouillé ici
pthread_mutex_lock(lock);
pthread_mutex_unlock(lock);
}
void *messageSender(void *lock)
{
int count = 1;
while (true)
{
consoleWrite(".");
sleep(1);
if ((count % 3) == 0)
{
//Ici, attendez que l'événement se produise.
suspend((pthread_mutex_t*)lock);
}
count++;
}
}
int main(int argc, char *argv[])
{
pthread_t tid;
pthread_mutex_t lock;
char buf[32];
pthread_mutex_init(&lock, NULL);
pthread_create(&tid, NULL, messageSender, &lock);
while (true)
{
input(buf, 32);
pthread_mutex_unlock(&lock); //L'opération de déverrouillage n'est pas garantie par les autres threads.
consoleWrite("unlocked.\n");
}
pthread_join(tid, NULL);
}
~~ Lorsque les données arrivent dans la file d'attente, utilisez le rappel et appuyez sur pthread_mutex_unlock ~~ Le déverrouillage de l'objet ~~ Mutex redémarre le thread. ~~ ~~ Dans la démo ci-dessus, la partie où les données sont stockées dans la file d'attente est remplacée par l'entrée du clavier. ~~
~~ Je l'ai implémenté aussi longtemps que je pouvais le faire sans penser aux performances, donc ~~ ~~ Si vous avez d'autres bonnes idées, faites-le. ~~ J'écrirai un exemple en utilisant pthread_cond_wait dans un autre article à une date ultérieure.
Référence: Section: Fonctions de la bibliothèque C de la page de manuel (3) PTHREAD_COND
//Différence de correction uniquement
typedef struct Suspend
{
pthread_mutex_t lockMutex;
pthread_cond_t lockCond;
} Suspend;
void suspend(Suspend *lock)
{
//Mauvaise utilisation
pthread_mutex_trylock(&lock->lockMutex);
pthread_cond_wait(&lock->lockCond,&lock->lockMutex);
pthread_mutex_unlock(&lock->lockMutex);
}
void SuspendInit(Suspend *lock)
{
pthread_cond_init(&lock->lockCond, NULL);
pthread_mutex_init(&lock->lockMutex, NULL);
}
int main(int argc, char *argv[])
{
pthread_t tid;
Suspend lock;
char buf[32];
SuspendInit(&lock);
pthread_create(&tid, NULL, messageSender, &lock);
while (true)
{
input(buf, 32);
pthread_cond_signal(&lock.lockCond);
consoleWrite("unlocked.\n");
}
pthread_join(tid, NULL);
}
~~ Tout d'abord, je sens que j'ai fixé les points signalés. ~~
typedef struct EventInfo
{
int state;
int read;
int write;
pthread_mutex_t mutex;
} EventInfo;
#define EventInfo_WAIT_BUSY 0
#define EventInfo_WAIT_READY 1
//Attendez que l'événement se produise
void EventInfoWait(EventInfo *lock)
{
uint8_t msg;
pthread_mutex_lock(&lock->mutex);
lock->state = EventInfo_WAIT_READY;
pthread_mutex_unlock(&lock->mutex);
int r = read(lock->read, &msg, sizeof(uint8_t));
}
//ne fais rien
void EventInfoRaisingEvent_None(EventInfo *lock)
{
}
//Avisez seulement.
void EventInfoRaisingEvent_Send(EventInfo *lock)
{
static uint8_t msg = 0xdeadbeef;
write(lock->write, &msg, sizeof(uint8_t));
}
//Organisez un événement
void EventInfoRaisingEvent(EventInfo *lock)
{
static void (*EventInfoWakeupSendMessage[2])(EventInfo * lock) =
{
EventInfoWakeupSendMessage_None,
EventInfoWakeupSendMessage_Send};
pthread_mutex_lock(&lock->mutex);
EventInfoWakeupSendMessage[lock->state](lock);
lock->state = EventInfo_WAIT_BUSY;
pthread_mutex_unlock(&lock->mutex);
}
void *messageSender(void *lock)
{
int count = 1;
while (true)
{
consoleWrite(".");
sleep(1);
if ((count % 3) == 0)
{
//Ici, attendez que l'événement se produise.
EventInfoWait((EventInfo *)lock);
}
count++;
}
}
int EventInfoInit(EventInfo *lock)
{
int pfd[2];
int r = pipe(pfd);
if (r != 0)
{
return -1;
}
lock->state = EventInfo_WAIT_BUSY;
fcntl(pfd[1], F_SETFL, O_NONBLOCK);
lock->read = pfd[0];
lock->write = pfd[1];
pthread_mutex_init(&lock->mutex, NULL);
return 0;
}
int main(int argc, char *argv[])
{
pthread_t tid;
EventInfo lock;
char buf[32];
EventInfoInit(&lock);
pthread_create(&tid, NULL, messageSender, &lock);
while (true)
{
input(buf, 32);
EventInfoRaisingEvent(&lock);
consoleWrite("unlocked.\n");
}
pthread_join(tid, NULL);
return 0;
}
Correctif, peut-être que cela devrait convenir car cela atteindra l'objectif initial.