Edited (Be, dass die Fehlerbehandlung der pthread Anrufe bewusst weggelassen wurden)
Sie können dies erreichen, indem er die Prüfung, ob die Warteschlange voll ist, mit der Funktion, die Sie in den Kommentaren erwähnt. Für diese Antwort werde ich annehmen, dass es bool is_queue_full(const queue*)
ist.
In Ihrem Testfall können Sie Szenario 3 garantieren, indem Sie den Producer erstellen und einen Consumer erstellen, wenn und nur wenn die Warteschlange voll ist. Wie bool is_queue_full (Warteschlange *); // Darf nicht den Mutex selbst, verwenden Sie es vielleicht markieren nur für internen Gebrauch
struct queue {
/* Actual queue stuff */
pthread_mutex_t queue_mutex;
pthread_cond_t read_condvar;
pthread_cond_t write_condvar;
};
void wait_until_queue_is_full (queue *q) {
pthread_mutex_lock(&q->queue_mutex);
while (!is_queue_full(q)){ //Use in loop because of Spurious wakeups
pthread_cond_wait(&q->write_condvar,&q->queue_mutex);
}
pthread_mutex_unlock(&q->queue_mutex);
}
bool test_writer_woke_up(queue *q);
bool test_case(){
queue *q = create_queue();
producer *p = create_producer(q);
wait_until_queue_is_full(q);
return test_writer_woke_up(q); //or cache the result and destroy your queue, but if your testrunner process will quit anyway...
}
wait_until_queue_is_full
wird nur prüfen, ob die Warteschlange voll ist, und wenn nicht, warten, wie jeder Leser, bis Ihr Schriftsteller aka Produzent hat machte es voll.Dann kann Ihr Testfall die Verbraucher mit etwas wie test_writer_woke_up
void intern_consume_stuff produzieren (Warteschlange q);/ Ihre intern Funktion, die Sachen aus der Warteschlange die absolute Zeit verwendet hat, nimmt, aber doesen't kümmern sich um die Synchronisations aka mutexes und condvar */
bool test_writer_woke_up(queue *q){
pthread_mutex_lock(&q->queue_mutex); //Could be omitted in this testcase (together with the 1 unlock below of course)
void intern_consume_stuff(queue *q);
pthread_mutex_unlock(&q->queue_mutex); //Could be omitted in this testcase (together with the 1 lock above of course)
pthread_cond_signal(&q->read_condvar);
/* Adjust these as you like to give your producer/writer time to wake up and produce something
*/
unsigned retry_count = 5;
unsigned sleep_time = 1;
//timed cond wait approach
for (; retry_count > 0; --retry_count){
pthread_mutex_lock(&q->queue_mutex);
struct timespec ts;
clock_gettime(CLOCK_REALTIME, &ts);
ts.tv_sec += sleep_time;
int timed_cond_rc = 0;
while (!is_queue_full(q) && timed_cond_rc == 0) {
timed_cond_rc = pthread_cond_timedwait(&q->write_condvar, &q->queue_mutex, &ts);
}
if (is_queue_full(q)) {
pthread_mutex_unlock(&q->queue_mutex);
return true;
}
assert(timed_cond_rc == ETIMEDOUT);
continue;
}
return false;
}
Wenn warten, da Sie relative Zeiten neu zu berechnen haben, oder, um die Dinge zu vereinfachen könnten Sie die for-Schleife mit diesem naiven Ansatz ersetzen
//naive busy approach
for (; retry_count > 0; --retry_count){
pthread_mutex_lock(q->queue_mutex);
const bool queue_full_result = is_queue_full(q);
pthread_mutex_unlock(q->queue_mutex);
if (queue_full_result){
return true;
} else {
pthread_yield();
sleep(sleep_time);
}
}
Starten Sie nur den Erzeugerfaden, warten Sie, bis er blockiert ist, und starten Sie dann den Verbraucher? – EOF
Gibt es API-Funktionen, mit denen Sie nur testen können, wenn die Warteschlange voll ist? – Superlokkus
@EOF - Wie programmiere ich programmatisch, dass der Produzententhread jetzt blockiert ist? (Ich suche etwas jenseits "warten Sie auf eine angemessene Zeitmenge") –