#include int N; #define THREADS 5 using namespace Upp; Mutex mutex; Semaphore todo; BiVector queue; void ProducerThread() { LOG("Producer start"); for(int i = 0; i < N; i++) { if(i % 1000 == 0) LOG(i); mutex.Enter(); int *x = new int; *x = i; queue.AddHead() = x; mutex.Leave(); todo.Release(); MemoryCheckDebug(); } LOG("Producer shutdown"); } void ConsumerThread() { LOG("Consumer start"); for(;;) { todo.Wait(); Mutex::Lock __(mutex); if(queue.GetCount()) { int *ptr = queue.Tail(); if(!ptr) break; queue.DropTail(); delete ptr; } MemoryCheckDebug(); } LOG("Consumer shutdown"); DUMP(queue.GetCount()); } void DoTest() { Thread producer[THREADS]; Thread consumer[THREADS]; for(int i = 0; i < THREADS; i++) { producer[i].Run(callback(ProducerThread)); consumer[i].Run(callback(ConsumerThread)); } for(int i = 0; i < THREADS; i++) { producer[i].Wait(); LOG("Producer #" << i << " terminated"); } mutex.Enter(); queue.AddHead(NULL); mutex.Leave(); for(int i = 0; i < THREADS; i++) todo.Release(); for(int i = 0; i < THREADS; i++) { consumer[i].Wait(); LOG("Consumer #" << i << " terminated"); } MemoryCheckDebug(); queue.Clear(); LOG("Round shutdown"); DUMP(MemoryUsedKb()); } CONSOLE_APP_MAIN { StdLogSetup(LOG_FILE|LOG_COUT); N = 1000; for(int i = 0; i < 100; i++) DoTest(); N = 100 * 1000; DoTest(); LOG("----------------- OK"); }