aboutsummaryrefslogtreecommitdiff
path: root/test/unit/allocator_test.cpp
blob: 2760cd10f7be9fd62d808f672c0c5e6f76a6b2f0 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
#include <memory>
#include <vector>

#include <cstdio>

#include "cppunit/cppunit_proxy.h"

#if !defined (STLPORT) || defined(_STLP_USE_NAMESPACES)
using namespace std;
#endif

//
// TestCase class
//
class AllocatorTest : public CPPUNIT_NS::TestCase
{
  CPPUNIT_TEST_SUITE(AllocatorTest);
  CPPUNIT_TEST(zero_allocation);
#if !defined (STLPORT) || defined (_STLP_USE_EXCEPTIONS)
  CPPUNIT_TEST(bad_alloc_test);
#endif
#if defined (STLPORT) && defined (_STLP_THREADS) && defined (_STLP_USE_PERTHREAD_ALLOC)
  CPPUNIT_TEST(per_thread_alloc);
#endif
  CPPUNIT_TEST_SUITE_END();

protected:
  void zero_allocation();
  void bad_alloc_test();
  void per_thread_alloc();
};

CPPUNIT_TEST_SUITE_REGISTRATION(AllocatorTest);

//
// tests implementation
//
void AllocatorTest::zero_allocation()
{
  typedef allocator<char> CharAllocator;
  CharAllocator charAllocator;

  char* buf = charAllocator.allocate(0);
  charAllocator.deallocate(buf, 0);

  charAllocator.deallocate(0, 0);
}

#if !defined (STLPORT) || defined (_STLP_USE_EXCEPTIONS)

struct BigStruct
{
  char _data[4096];
};

void AllocatorTest::bad_alloc_test()
{
  typedef allocator<BigStruct> BigStructAllocType;
  BigStructAllocType bigStructAlloc;

  try {
    //Lets try to allocate almost 4096 Go (on most of the platforms) of memory:
    BigStructAllocType::pointer pbigStruct = bigStructAlloc.allocate(1024 * 1024 * 1024);

    //Allocation failed but no exception thrown
    CPPUNIT_ASSERT( pbigStruct != 0 );

    // Just it case it succeeds:
    bigStructAlloc.deallocate(pbigStruct, 1024 * 1024 * 1024);
  }
  catch (bad_alloc const&) {
  }
  catch (...) {
    //We shouldn't be there:
    //Not bad_alloc exception thrown.
    CPPUNIT_FAIL;
  }
}
#endif

#if defined (STLPORT) && defined (_STLP_THREADS) && defined (_STLP_USE_PERTHREAD_ALLOC)
#  include <pthread.h>

class SharedDatas
{
public:
  typedef vector<int, per_thread_allocator<int> > thread_vector;

  SharedDatas(size_t nbElems) : threadVectors(nbElems, (thread_vector*)0) {
    pthread_mutex_init(&mutex, 0);
    pthread_cond_init(&condition, 0);
  }

  ~SharedDatas() {
    for (size_t i = 0; i < threadVectors.size(); ++i) {
      delete threadVectors[i];
    }
  }

  size_t initThreadVector() {
    size_t ret;

    pthread_mutex_lock(&mutex);

    for (size_t i = 0; i < threadVectors.size(); ++i) {
      if (threadVectors[i] == 0) {
        threadVectors[i] = new thread_vector();
        ret = i;
        break;
      }
    }

    if (ret != threadVectors.size() - 1) {
      //We wait for other thread(s) to call this method too:
      printf("Thread %d wait\n", ret);
      pthread_cond_wait(&condition, &mutex);
    }
    else {
      //We are the last thread calling this method, we signal this
      //to the other thread(s) that might be waiting:
      printf("Thread %d signal\n", ret);
      pthread_cond_signal(&condition);
    }

    pthread_mutex_unlock(&mutex);

    return ret;
  }

  thread_vector& getThreadVector(size_t index) {
    //We return other thread thread_vector instance:
    return *threadVectors[(index + 1 == threadVectors.size()) ? 0 : index + 1];
  }

private:
  pthread_mutex_t mutex;
  pthread_cond_t condition;
  vector<thread_vector*> threadVectors;
};

void* f(void* pdatas) {
  SharedDatas *psharedDatas = (SharedDatas*)pdatas;

  int threadIndex = psharedDatas->initThreadVector();

  for (int i = 0; i < 100; ++i) {
    psharedDatas->getThreadVector(threadIndex).push_back(i);
  }

  return 0;
}

void AllocatorTest::per_thread_alloc()
{
  const size_t nth = 2;
  SharedDatas datas(nth);
  pthread_t t[nth];

  size_t i;
  for (i = 0; i < nth; ++i) {
    pthread_create(&t[i], 0, f, &datas);
  }

  for (i = 0; i < nth; ++i ) {
    pthread_join(t[i], 0);
  }
}
#endif