1 #include <memory> 2 #include <vector> 3 4 #include <cstdio> 5 6 #include "cppunit/cppunit_proxy.h" 7 8 #if !defined (STLPORT) || defined(_STLP_USE_NAMESPACES) 9 using namespace std; 10 #endif 11 12 // 13 // TestCase class 14 // 15 class AllocatorTest : public CPPUNIT_NS::TestCase 16 { 17 CPPUNIT_TEST_SUITE(AllocatorTest); 18 CPPUNIT_TEST(zero_allocation); 19 #if !defined (STLPORT) || defined (_STLP_USE_EXCEPTIONS) 20 CPPUNIT_TEST(bad_alloc_test); 21 #endif 22 #if defined (STLPORT) && defined (_STLP_THREADS) && defined (_STLP_USE_PERTHREAD_ALLOC) 23 CPPUNIT_TEST(per_thread_alloc); 24 #endif 25 CPPUNIT_TEST_SUITE_END(); 26 27 protected: 28 void zero_allocation(); 29 void bad_alloc_test(); 30 void per_thread_alloc(); 31 }; 32 33 CPPUNIT_TEST_SUITE_REGISTRATION(AllocatorTest); 34 35 // 36 // tests implementation 37 // 38 void AllocatorTest::zero_allocation() 39 { 40 typedef allocator<char> CharAllocator; 41 CharAllocator charAllocator; 42 43 char* buf = charAllocator.allocate(0); 44 charAllocator.deallocate(buf, 0); 45 46 charAllocator.deallocate(0, 0); 47 } 48 49 #if !defined (STLPORT) || defined (_STLP_USE_EXCEPTIONS) 50 51 struct BigStruct 52 { 53 char _data[4096]; 54 }; 55 56 void AllocatorTest::bad_alloc_test() 57 { 58 typedef allocator<BigStruct> BigStructAllocType; 59 BigStructAllocType bigStructAlloc; 60 61 try { 62 //Lets try to allocate almost 4096 Go (on most of the platforms) of memory: 63 BigStructAllocType::pointer pbigStruct = bigStructAlloc.allocate(1024 * 1024 * 1024); 64 65 //Allocation failed but no exception thrown 66 CPPUNIT_ASSERT( pbigStruct != 0 ); 67 68 // Just it case it succeeds: 69 bigStructAlloc.deallocate(pbigStruct, 1024 * 1024 * 1024); 70 } 71 catch (bad_alloc const&) { 72 } 73 catch (...) { 74 //We shouldn't be there: 75 //Not bad_alloc exception thrown. 76 CPPUNIT_FAIL; 77 } 78 } 79 #endif 80 81 #if defined (STLPORT) && defined (_STLP_THREADS) && defined (_STLP_USE_PERTHREAD_ALLOC) 82 # include <pthread.h> 83 84 class SharedDatas 85 { 86 public: 87 typedef vector<int, per_thread_allocator<int> > thread_vector; 88 89 SharedDatas(size_t nbElems) : threadVectors(nbElems, (thread_vector*)0) { 90 pthread_mutex_init(&mutex, 0); 91 pthread_cond_init(&condition, 0); 92 } 93 94 ~SharedDatas() { 95 for (size_t i = 0; i < threadVectors.size(); ++i) { 96 delete threadVectors[i]; 97 } 98 } 99 100 size_t initThreadVector() { 101 size_t ret; 102 103 pthread_mutex_lock(&mutex); 104 105 for (size_t i = 0; i < threadVectors.size(); ++i) { 106 if (threadVectors[i] == 0) { 107 threadVectors[i] = new thread_vector(); 108 ret = i; 109 break; 110 } 111 } 112 113 if (ret != threadVectors.size() - 1) { 114 //We wait for other thread(s) to call this method too: 115 printf("Thread %d wait\n", ret); 116 pthread_cond_wait(&condition, &mutex); 117 } 118 else { 119 //We are the last thread calling this method, we signal this 120 //to the other thread(s) that might be waiting: 121 printf("Thread %d signal\n", ret); 122 pthread_cond_signal(&condition); 123 } 124 125 pthread_mutex_unlock(&mutex); 126 127 return ret; 128 } 129 130 thread_vector& getThreadVector(size_t index) { 131 //We return other thread thread_vector instance: 132 return *threadVectors[(index + 1 == threadVectors.size()) ? 0 : index + 1]; 133 } 134 135 private: 136 pthread_mutex_t mutex; 137 pthread_cond_t condition; 138 vector<thread_vector*> threadVectors; 139 }; 140 141 void* f(void* pdatas) { 142 SharedDatas *psharedDatas = (SharedDatas*)pdatas; 143 144 int threadIndex = psharedDatas->initThreadVector(); 145 146 for (int i = 0; i < 100; ++i) { 147 psharedDatas->getThreadVector(threadIndex).push_back(i); 148 } 149 150 return 0; 151 } 152 153 void AllocatorTest::per_thread_alloc() 154 { 155 const size_t nth = 2; 156 SharedDatas datas(nth); 157 pthread_t t[nth]; 158 159 size_t i; 160 for (i = 0; i < nth; ++i) { 161 pthread_create(&t[i], 0, f, &datas); 162 } 163 164 for (i = 0; i < nth; ++i ) { 165 pthread_join(t[i], 0); 166 } 167 } 168 #endif 169