test_condition.c (5710B)
1 /* Copyright (C) 2013-2023, 2025 Vincent Forest (vaplv@free.fr) 2 * 3 * The RSys library is free software: you can redistribute it and/or modify 4 * it under the terms of the GNU General Public License as published 5 * by the Free Software Foundation, either version 3 of the License, or 6 * (at your option) any later version. 7 * 8 * The RSys library is distributed in the hope that it will be useful, 9 * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 * GNU General Public License for more details. 12 * 13 * You should have received a copy of the GNU General Public License 14 * along with the RSys library. If not, see <http://www.gnu.org/licenses/>. */ 15 16 #define _POSIX_C_SOURCE 199506L /* POSIX threads */ 17 18 #include "condition.h" 19 #include "list.h" 20 21 #include <string.h> 22 #include <pthread.h> 23 24 static const char* src_str[] = { 25 "Rcvfbqr 1, XARR-QRRC VA GUR QRNQ:\n\ 26 ---------------------------------", 27 28 "BAPR LBH ORNG GUR OVT ONQNFFRF NAQ PYRNA BHG GUR ZBBA ONFR LBH'ER FHCCBFRQ GB\n\ 29 JVA, NERA'G LBH? NERA'G LBH? JURER'F LBHE SNG ERJNEQ NAQ GVPXRG UBZR? JUNG\n\ 30 GUR URYY VF GUVF? VG'F ABG FHCCBFRQ GB RAQ GUVF JNL!", 31 32 "VG FGVAXF YVXR EBGGRA ZRNG, OHG YBBXF YVXR GUR YBFG QRVZBF ONFR. YBBXF YVXR\n\ 33 LBH'ER FGHPX BA GUR FUBERF BS URYY. GUR BAYL JNL BHG VF GUEBHTU.", 34 35 "GB PBAGVAHR GUR QBBZ RKCREVRAPR, CYNL GUR FUBERF BS URYY NAQ VGF NZNMVAT\n\ 36 FRDHRY, VASREAB!", 37 38 "Rcvfbqr 2, GUR FUBERF BS URYY:\n\ 39 ------------------------------", 40 41 "LBH'IR QBAR VG! GUR UVQRBHF PLORE- QRZBA YBEQ GUNG EHYRQ GUR YBFG QRVZBF ZBBA\n\ 42 ONFR UNF ORRA FYNVA NAQ LBH NER GEVHZCUNAG! OHG ... JURER NER LBH? LBH\n\ 43 PYNZORE GB GUR RQTR BS GUR ZBBA NAQ YBBX QBJA GB FRR GUR NJSHY GEHGU.", 44 45 "QRVZBF SYBNGF NOBIR URYY VGFRYS! LBH'IR ARIRE URNEQ BS NALBAR RFPNCVAT SEBZ\n\ 46 URYY, OHG LBH'YY ZNXR GUR ONFGNEQF FBEEL GURL RIRE URNEQ BS LBH! DHVPXYL, LBH\n\ 47 ENCCRY QBJA GB GUR FHESNPR BS URYY.", 48 49 "ABJ, VG'F BA GB GUR SVANY PUNCGRE BS QBBZ! -- VASREAB.", 50 51 "Rcvfbqr 3, VASREAB:\n\ 52 -------------------", 53 54 "GUR YBNGUFBZR FCVQREQRZBA GUNG ZNFGREZVAQRQ GUR VAINFVBA BS GUR ZBBA ONFRF\n\ 55 NAQ PNHFRQ FB ZHPU QRNGU UNF UNQ VGF NFF XVPXRQ SBE NYY GVZR.", 56 57 "N UVQQRA QBBEJNL BCRAF NAQ LBH RAGRE. LBH'IR CEBIRA GBB GBHTU SBE URYY GB\n\ 58 PBAGNVA, NAQ ABJ URYY NG YNFG CYNLF SNVE -- SBE LBH RZRETR SEBZ GUR QBBE GB\n\ 59 FRR GUR TERRA SVRYQF BS RNEGU! UBZR NG YNFG.", 60 61 "LBH JBAQRE JUNG'F ORRA UNCCRAVAT BA RNEGU JUVYR LBH JRER ONGGYVAT RIVY\n\ 62 HAYRNFURQ. VG'F TBBQ GUNG AB URYY- FCNJA PBHYQ UNIR PBZR GUEBHTU GUNG QBBE\n\ 63 JVGU LBH ...", 64 65 "Rcvfbqr 4, GUL SYRFU PBAFHZRQ:\n\ 66 ------------------------------", 67 68 "GUR FCVQRE ZNFGREZVAQ ZHFG UNIR FRAG SBEGU VGF YRTVBAF BS URYYFCNJA ORSBER\n\ 69 LBHE SVANY PBASEBAGNGVBA JVGU GUNG GREEVOYR ORNFG SEBZ URYY. OHG LBH FGRCCRQ\n\ 70 SBEJNEQ NAQ OEBHTUG SBEGU RGREANY QNZANGVBA NAQ FHSSREVAT HCBA GUR UBEQR NF N\n\ 71 GEHR UREB JBHYQ VA GUR SNPR BS FBZRGUVAT FB RIVY.", 72 73 "ORFVQRF, FBZRBAR JNF TBAAN CNL SBE JUNG UNCCRARQ GB QNVFL, LBHE CRG ENOOVG.", 74 75 "OHG ABJ, LBH FRR FCERNQ ORSBER LBH ZBER CBGRAGVNY CNVA NAQ TVOOVGHQR NF N\n\ 76 ANGVBA BS QRZBAF EHA NZBX VA BHE PVGVRF.", 77 78 "ARKG FGBC, URYY BA RNEGU!" 79 }; 80 81 struct stream 82 { 83 struct list_node list_fill; 84 struct list_node list_flush; 85 struct mutex* mutex; 86 struct cond* cond_fill; 87 struct cond* cond_flush; 88 }; 89 90 struct buff 91 { 92 struct list_node node; 93 char scratch[1024]; 94 }; 95 96 static void* 97 read(void* arg) 98 { 99 struct stream* stream = arg; 100 size_t i = 0; 101 ASSERT(stream); 102 103 FOR_EACH(i, 0, sizeof(src_str)/sizeof(const char*)) { 104 struct list_node* buff_node = NULL; 105 struct buff* buff = NULL; 106 107 mutex_lock(stream->mutex); 108 if(is_list_empty(&stream->list_flush)) { 109 cond_wait(stream->cond_flush, stream->mutex); 110 } 111 mutex_unlock(stream->mutex); 112 113 buff_node = list_head(&stream->list_flush); 114 buff = CONTAINER_OF(buff_node, struct buff, node); 115 CHK(strcmp(buff->scratch, src_str[i]) == 0); 116 printf("\n%s\n", buff->scratch); 117 118 mutex_lock(stream->mutex); 119 list_move_tail(buff_node, &stream->list_fill); 120 mutex_unlock(stream->mutex); 121 122 cond_broadcast(stream->cond_fill); 123 } 124 return NULL; 125 } 126 127 static void* 128 write(void* arg) 129 { 130 struct stream* stream = arg; 131 size_t i = 0; 132 ASSERT(stream); 133 134 FOR_EACH(i, 0, sizeof(src_str)/sizeof(const char*)) { 135 struct list_node* buff_node = NULL; 136 struct buff* buff = NULL; 137 138 mutex_lock(stream->mutex); 139 if(is_list_empty(&stream->list_fill)) { 140 cond_wait(stream->cond_fill, stream->mutex); 141 } 142 mutex_unlock(stream->mutex); 143 144 buff_node = list_head(&stream->list_fill); 145 buff = CONTAINER_OF(buff_node, struct buff, node); 146 147 ASSERT(sizeof(buff->scratch)/sizeof(char) > strlen(src_str[i])); 148 strcpy(buff->scratch, src_str[i]); 149 150 mutex_lock(stream->mutex); 151 list_move_tail(buff_node, &stream->list_flush); 152 mutex_unlock(stream->mutex); 153 154 cond_broadcast(stream->cond_flush); 155 } 156 return NULL; 157 } 158 159 int 160 main(int argc, char** argv) 161 { 162 struct buff buff[2]; 163 struct stream stream; 164 pthread_t thread; 165 (void)argc, (void)argv; 166 167 list_init(&stream.list_fill); 168 list_init(&stream.list_flush); 169 stream.mutex = mutex_create(); 170 CHK(stream.mutex != NULL); 171 stream.cond_flush = cond_create(); 172 CHK(stream.cond_flush != NULL); 173 stream.cond_fill = cond_create(); 174 CHK(stream.cond_fill != NULL); 175 176 list_init(&buff[0].node); 177 list_init(&buff[1].node); 178 list_add(&stream.list_fill, &buff[0].node); 179 list_add(&stream.list_fill, &buff[1].node); 180 181 CHK(pthread_create(&thread, NULL, read, &stream) == 0); /* Sub thread */ 182 write(&stream); 183 CHK(pthread_join(thread, NULL) == 0); 184 185 mutex_destroy(stream.mutex); 186 cond_destroy(stream.cond_flush); 187 cond_destroy(stream.cond_fill); 188 return 0; 189 }