#include #include /* Copyright (c) 1999 Nathan Meyers $Id: threadcount.C,v 1.2 1999/11/10 17:48:17 nathanm Exp $ Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ // threadcount: A multi-threaded program that counts to 20 // This is our main counter and its thread-safety components class counter { public: pthread_cond_t condition; pthread_mutex_t mutex; int value; counter() { condition = (pthread_cond_t)PTHREAD_COND_INITIALIZER; mutex = (pthread_mutex_t)PTHREAD_MUTEX_INITIALIZER; value = 0; } }; // This class encapsulates functionality to increment the counter // when it is odd class odd_counter { counter &ctr; odd_counter(counter &c) : ctr(c) {} void count() { // Lock the counter pthread_mutex_lock(&ctr.mutex); // Count to 20 while (ctr.value < 20) { // If value is currently even, wait for a change while (!(ctr.value & 1)) pthread_cond_wait(&ctr.condition, &ctr.mutex); // Change the value ctr.value++; // Signal the change pthread_cond_broadcast(&ctr.condition); // Print results cout << ctr.value << '\n'; } pthread_mutex_unlock(&ctr.mutex); } public: // A static function (suitable for passing to pthread_create) to // create and start up our counter static void *startup(void *c) { // Create an automatic instance of class and call count() method odd_counter(*(counter *)c).count(); return 0; } }; // This class encapsulates functionality to increment the counter // when it is even class even_counter { counter &ctr; even_counter(counter &c) : ctr(c) {} void count() { // Lock the counter pthread_mutex_lock(&ctr.mutex); // Count to 20 while (ctr.value < 19) { // If value is currently odd, wait for a change while (ctr.value & 1) pthread_cond_wait(&ctr.condition, &ctr.mutex); // Change the value ctr.value++; // Signal the change pthread_cond_broadcast(&ctr.condition); // Print results cout << ctr.value << '\n'; } pthread_mutex_unlock(&ctr.mutex); } public: // A static function (suitable for passing to pthread_create) to // create and start up our counter static void *startup(void *c) { // Create an automatic instance of class and call count() method even_counter(*(counter *)c).count(); return 0; } }; int main() { // Our counter counter cnt; pthread_t thread1, thread2; // Start first thread with odd_counter, passing it our counter pthread_create(&thread1, NULL, odd_counter::startup, &cnt); // Start second thread with even_counter, passing it our counter pthread_create(&thread2, NULL, even_counter::startup, &cnt); // Hang around for threads to end pthread_join(thread1, NULL); pthread_join(thread2, NULL); // Done! exit(0); }