1249746Sdteske// 2002-01-23 Loren J. Rittle <rittle@labs.mot.com> <ljrittle@acm.org> 2252980Sdteske// 3238438Sdteske// Copyright (C) 2002, 2003 Free Software Foundation, Inc. 4238438Sdteske// 5238438Sdteske// This file is part of the GNU ISO C++ Library. This library is free 6238438Sdteske// software; you can redistribute it and/or modify it under the 7238438Sdteske// terms of the GNU General Public License as published by the 8238438Sdteske// Free Software Foundation; either version 2, or (at your option) 9238438Sdteske// any later version. 10238438Sdteske// 11238438Sdteske// This library is distributed in the hope that it will be useful, 12238438Sdteske// but WITHOUT ANY WARRANTY; without even the implied warranty of 13238438Sdteske// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14252987Sdteske// GNU General Public License for more details. 15238438Sdteske// 16238438Sdteske// You should have received a copy of the GNU General Public License along 17238438Sdteske// with this library; see the file COPYING. If not, write to the Free 18252987Sdteske// Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, 19238438Sdteske// USA. 20238438Sdteske 21238438Sdteske// { dg-do run { target *-*-openbsd* *-*-freebsd* *-*-netbsd* *-*-linux* *-*-solaris* *-*-cygwin *-*-darwin* } } 22238438Sdteske// { dg-options "-pthread" { target *-*-openbsd* *-*-freebsd* *-*-netbsd* *-*-linux* } } 23238438Sdteske// { dg-options "-pthreads" { target *-*-solaris* } } 24238438Sdteske 25238438Sdteske// This multi-threading C++/STL/POSIX code adheres to rules outlined here: 26238438Sdteske// http://www.sgi.com/tech/stl/thread_safety.html 27238438Sdteske// 28238438Sdteske// It is believed to exercise the allocation code in a manner that 29238438Sdteske// should reveal memory leaks (and, under rare cases, race conditions, 30249746Sdteske// if the STL threading support is fubar'd). 31249746Sdteske 32249746Sdteske#include <list> 33249746Sdteske 34249746Sdteske// Do not include <pthread.h> explicitly; if threads are properly 35238438Sdteske// configured for the port, then it is picked up free from STL headers. 36238438Sdteske 37238438Sdteske#if __GTHREADS 38using namespace std; 39 40const int thread_cycles = 10; 41const int thread_pairs = 10; 42const unsigned max_size = 100; 43const int iters = 10000; 44 45class task_queue 46{ 47public: 48 task_queue () 49 { 50 pthread_mutex_init (&fooLock, NULL); 51 pthread_cond_init (&fooCond1, NULL); 52 pthread_cond_init (&fooCond2, NULL); 53 } 54 ~task_queue () 55 { 56 pthread_mutex_destroy (&fooLock); 57 pthread_cond_destroy (&fooCond1); 58 pthread_cond_destroy (&fooCond2); 59 } 60 list<int> foo; 61 pthread_mutex_t fooLock; 62 pthread_cond_t fooCond1; 63 pthread_cond_t fooCond2; 64}; 65 66void* 67produce (void* t) 68{ 69 task_queue& tq = *(static_cast<task_queue*> (t)); 70 int num = 0; 71 while (num < iters) 72 { 73 pthread_mutex_lock (&tq.fooLock); 74 while (tq.foo.size () >= max_size) 75 pthread_cond_wait (&tq.fooCond1, &tq.fooLock); 76 tq.foo.push_back (num++); 77 pthread_cond_signal (&tq.fooCond2); 78 pthread_mutex_unlock (&tq.fooLock); 79 } 80 return 0; 81} 82 83void* 84consume (void* t) 85{ 86 task_queue& tq = *(static_cast<task_queue*> (t)); 87 int num = 0; 88 while (num < iters) 89 { 90 pthread_mutex_lock (&tq.fooLock); 91 while (tq.foo.size () == 0) 92 pthread_cond_wait (&tq.fooCond2, &tq.fooLock); 93 if (tq.foo.front () != num++) 94 abort (); 95 tq.foo.pop_front (); 96 pthread_cond_signal (&tq.fooCond1); 97 pthread_mutex_unlock (&tq.fooLock); 98 } 99 return 0; 100} 101 102int 103main (int argc, char** argv) 104{ 105 pthread_t prod[thread_pairs]; 106 pthread_t cons[thread_pairs]; 107 108 task_queue* tq[thread_pairs]; 109 110#if defined(__sun) && defined(__svr4__) 111 pthread_setconcurrency (thread_pairs * 2); 112#endif 113 114 for (int j = 0; j < thread_cycles; j++) 115 { 116 for (int i = 0; i < thread_pairs; i++) 117 { 118 tq[i] = new task_queue; 119 pthread_create (&prod[i], NULL, produce, static_cast<void*> (tq[i])); 120 pthread_create (&cons[i], NULL, consume, static_cast<void*> (tq[i])); 121 } 122 123 for (int i = 0; i < thread_pairs; i++) 124 { 125 pthread_join (prod[i], NULL); 126 pthread_join (cons[i], NULL); 127#if defined(__FreeBSD__) && __FreeBSD__ < 5 128 // These lines are not required by POSIX since a successful 129 // join is suppose to detach as well... 130 pthread_detach (prod[i]); 131 pthread_detach (cons[i]); 132 // ...but they are according to the FreeBSD 4.X code base 133 // or else you get a memory leak. 134#endif 135 delete tq[i]; 136 } 137 } 138 139 return 0; 140} 141#else 142int main (void) {} 143#endif 144