35 #include <gtest/gtest.h> 40 #include <boost/thread.hpp> 52 uint32_t* item =
static_cast<uint32_t*
>(pool.
allocate());
54 EXPECT_EQ(*item, 5UL);
58 item =
static_cast<uint32_t*
>(pool.
allocate());
60 EXPECT_EQ(*item, 6UL);
65 const uint32_t count = 5;
69 std::vector<uint32_t*> items;
72 for (uint32_t i = 0; i < count; ++i)
74 items.push_back(static_cast<uint32_t*>(pool.
allocate()));
75 ASSERT_TRUE(items[i]);
76 EXPECT_EQ(*items[i], 5UL);
81 pool.
free(items.back());
83 items.push_back(static_cast<uint32_t*>(pool.
allocate()));
84 ASSERT_TRUE(items.back());
87 std::set<uint32_t*>
set;
88 set.insert(items.begin(), items.end());
89 EXPECT_EQ(
set.size(), count);
93 boost::mutex g_debug_mutex;
94 std::vector<FreeList::Debug> g_debug;
96 std::ostream& operator<<(std::ostream& o,
const FreeList::Debug::Item& i)
99 o << (i.success ? 1 : 0);
103 o << ((i.op == FreeList::Debug::Alloc) ? std::string(
"alloc") : std::string(
"free "));
104 o << std::string(
" head: ");
107 o << std::string(
" new_head: ");
109 o <<
" addr:" << (uint32_t*)i.addr;
117 : start(
ros::WallTime::now())
126 void threadFunc(
FreeList& pool, ros::atomic<bool>& done, ros::atomic<bool>& failed, boost::barrier& b)
133 uint64_t alloc_count = 0;
136 for (uint32_t i = 0; i < 10; ++i)
138 vals[i] =
static_cast<uint32_t*
>(pool.
allocate());
147 ROS_ERROR_STREAM(
"Thread " << boost::this_thread::get_id() <<
" failed to allocate");
151 for (uint32_t i = 0; i < 10; ++i)
157 ROS_ERROR_STREAM(
"Thread " << boost::this_thread::get_id() <<
" val " << vals[i] <<
" " << i <<
" = " << *vals[i]);
168 boost::mutex::scoped_lock lock(g_debug_mutex);
169 g_debug.push_back(*pool.getDebug());
180 const uint32_t thread_count = boost::thread::hardware_concurrency() * 2;
181 FreeList pool(4, thread_count * 10);
182 ros::atomic<bool> done(
false);
183 ros::atomic<bool> failed(
false);
184 boost::thread_group tg;
185 boost::barrier bar(thread_count);
186 for (uint32_t i = 0; i < thread_count; ++i)
188 tg.create_thread(boost::bind(
threadFunc, boost::ref(pool), boost::ref(done), boost::ref(failed), boost::ref(bar)));
207 std::vector<std::vector<FreeList::Debug::Item>::iterator> its;
208 its.resize(g_debug.size());
209 for (
size_t i = 0; i < its.size(); ++i)
211 int32_t start = std::max((int32_t)g_debug[i].items.size() - 10000, 0);
213 its[i] = g_debug[i].items.begin() + start;
219 for (
size_t j = 0; j < its.size(); ++j)
221 if (its[j] != g_debug[j].items.end() && its[j]->time < time)
233 ROS_ERROR_STREAM(
"[" << std::setw(20) << g_debug[ind].thread <<
"] " << *its[ind]);
239 ASSERT_TRUE(!failed.load());
244 const uint32_t count = 5;
247 std::vector<uint32_t*> items;
248 items.reserve(count);
252 for (uint32_t i = 0; i < count; ++i)
254 items.push_back(static_cast<uint32_t*>(pool.
allocate()));
258 for (uint32_t i = 0; i < count; ++i)
267 int main(
int argc,
char** argv)
269 testing::InitGoogleTest(&argc, argv);
270 return RUN_ALL_TESTS();
void free(void const *mem)
Free a block of memory allocated from this FreeList.
void * allocate()
Allocate a single block from this FreeList.
TEST(FreeList, oneElement)
void threadFunc(FreeList &pool, ros::atomic< bool > &done, ros::atomic< bool > &failed, boost::barrier &b)
bool hasOutstandingAllocations()
Returns whether or not this FreeList currently has any outstanding allocations.
#define ROS_INFO_STREAM(args)
#define ROS_ERROR_STREAM(args)
A lock-free (not wait-free) statically-sized free-list implemented with CAS.
void constructAll(const T &tmpl)
Construct all the blocks with a specific template. If you call this you must call destructAll() prior...
int main(int argc, char **argv)