-
Notifications
You must be signed in to change notification settings - Fork 20
/
Copy pathProducers.cpp
126 lines (109 loc) · 3.4 KB
/
Producers.cpp
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
#include "Producers.h"
#include <iostream>
#include <stdlib.h>
#include <string.h>
void *allocateAndUse(ThreadObject &myThread, size_t &memUsed, size_t sz) {
void *ptr = myThread.allocate(sz);
memUsed += sz;
if (ptr != nullptr) {
memset(ptr, 0, sz);
}
return ptr;
}
// Simple Producer
SimpleProducer::SimpleProducer(int allocSize, int numAllocs)
: allocSize_(allocSize), allocsLeft_(numAllocs) {}
Allocation SimpleProducer::run(ThreadObject &myThread, size_t memUsageHint,
ProducerStatus &retStatus) {
size_t memUsed = 0;
while (true) {
if (this->allocsLeft_ <= 0) {
retStatus = ProducerStatus::Done;
return Allocation();
}
if (memUsed >= memUsageHint) {
retStatus = ProducerStatus::Yield;
return Allocation();
}
void *ptr = allocateAndUse(myThread, memUsed, this->allocSize_);
if (ptr == nullptr) {
retStatus = ProducerStatus::AllocationFailed;
return Allocation();
}
this->allocsLeft_ -= 1;
free(ptr);
}
}
void SimpleProducer::cleanup() {}
// Vector Producer
VectorProducer::VectorProducer(size_t maxSize, size_t initialSize, int lifetime)
: maxSize_(maxSize), initialSize_(initialSize), currentSize_(0),
ptr_(nullptr), lifetime_(lifetime) {}
Allocation VectorProducer::run(ThreadObject &myThread, size_t memUsageHint,
ProducerStatus &retStatus) {
size_t memUsed = 0;
if (this->currentSize_ == 0) {
this->ptr_ = allocateAndUse(myThread, memUsed, this->initialSize_);
if (this->ptr_ == nullptr) {
retStatus = ProducerStatus::AllocationFailed;
return Allocation();
}
this->currentSize_ = this->initialSize_;
}
while (true) {
if (this->currentSize_ >= this->maxSize_) {
retStatus = ProducerStatus::Done;
return Allocation({this->ptr_}, this->lifetime_);
}
if (memUsed >= memUsageHint) {
retStatus = ProducerStatus::Yield;
return Allocation();
}
free(this->ptr_);
this->currentSize_ *= 2;
this->ptr_ = allocateAndUse(myThread, memUsed, this->currentSize_);
if (ptr_ == nullptr) {
retStatus = ProducerStatus::AllocationFailed;
return Allocation();
}
}
}
void VectorProducer::cleanup() {
if (this->ptr_ != nullptr) {
free(this->ptr_);
}
}
// LinkedList Producer
Allocation LinkedListProducer::run(ThreadObject &myThread, size_t memUsageHint,
ProducerStatus &retStatus) {
size_t memUsed = 0;
while (true) {
if (this->nodesRemaining_ <= 0) {
retStatus = ProducerStatus::Done;
return Allocation(std::move(this->toFree_), this->lifetime_);
}
if (memUsed >= memUsageHint) {
retStatus = ProducerStatus::Yield;
return Allocation();
}
void *newNode = allocateAndUse(myThread, memUsed, this->nodeSize_);
if (newNode == nullptr) {
retStatus = ProducerStatus::AllocationFailed;
return Allocation();
}
nodesRemaining_ -= 1;
this->toFree_.push_back(newNode);
}
}
void LinkedListProducer::cleanup() {
for (auto &ptr : this->toFree_) {
free(ptr);
}
}
// allocate [numNodes] blocks of size [nodeSize] with lifetime [lifetime]
LinkedListProducer::LinkedListProducer(size_t nodeSize, int numNodes,
int lifetime)
: nodeSize_(nodeSize), nodesRemaining_(numNodes), lifetime_(lifetime),
toFree_() {
this->toFree_.reserve(numNodes);
}