Home | History | Annotate | Download | only in unit
      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