Skip to content

Commit 89e431b

Browse files
authored
Merge pull request #69 from kswiecicki/pool-create-owning
Add the umfPoolCreateEx internal function
2 parents dbdc5de + 528e96d commit 89e431b

File tree

6 files changed

+160
-0
lines changed

6 files changed

+160
-0
lines changed

src/memory_pool.c

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,37 @@
1515
#include <assert.h>
1616
#include <stdlib.h>
1717

18+
umf_result_t umfPoolCreateEx(const umf_memory_pool_ops_t *pool_ops,
19+
void *pool_params,
20+
const umf_memory_provider_ops_t *provider_ops,
21+
void *provider_params,
22+
umf_memory_pool_handle_t *hPool) {
23+
if (!pool_ops || !provider_ops || !hPool) {
24+
return UMF_RESULT_ERROR_INVALID_ARGUMENT;
25+
}
26+
27+
umf_memory_provider_handle_t provider = NULL;
28+
umf_result_t ret =
29+
umfMemoryProviderCreate(provider_ops, provider_params, &provider);
30+
if (ret != UMF_RESULT_SUCCESS) {
31+
return ret;
32+
}
33+
assert(provider != NULL);
34+
35+
umf_memory_pool_handle_t pool = NULL;
36+
ret = umfPoolCreate(pool_ops, provider, pool_params, &pool);
37+
if (ret != UMF_RESULT_SUCCESS) {
38+
umfMemoryProviderDestroy(provider);
39+
return ret;
40+
}
41+
assert(pool != NULL);
42+
43+
pool->own_provider = true;
44+
*hPool = pool;
45+
46+
return UMF_RESULT_SUCCESS;
47+
}
48+
1849
void *umfPoolMalloc(umf_memory_pool_handle_t hPool, size_t size) {
1950
return hPool->ops.malloc(hPool->pool_priv, size);
2051
}

src/memory_pool_default.c

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ umf_result_t umfPoolCreate(const umf_memory_pool_ops_t *ops,
3030
assert(ops->version == UMF_VERSION_CURRENT);
3131

3232
pool->provider = provider;
33+
pool->own_provider = false;
3334

3435
pool->ops = *ops;
3536
ret = ops->initialize(pool->provider, params, &pool->pool_priv);
@@ -44,6 +45,12 @@ umf_result_t umfPoolCreate(const umf_memory_pool_ops_t *ops,
4445

4546
void umfPoolDestroy(umf_memory_pool_handle_t hPool) {
4647
hPool->ops.finalize(hPool->pool_priv);
48+
if (hPool->own_provider) {
49+
// Destroy associated memory provider.
50+
umf_memory_provider_handle_t hProvider = NULL;
51+
umfPoolGetMemoryProvider(hPool, &hProvider);
52+
umfMemoryProviderDestroy(hProvider);
53+
}
4754
free(hPool);
4855
}
4956

src/memory_pool_internal.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,12 @@
1111
#define UMF_MEMORY_POOL_INTERNAL_H 1
1212

1313
#include <umf/base.h>
14+
#include <umf/memory_pool.h>
1415
#include <umf/memory_pool_ops.h>
1516
#include <umf/memory_provider.h>
1617

18+
#include <stdbool.h>
19+
1720
#ifdef __cplusplus
1821
extern "C" {
1922
#endif
@@ -24,8 +27,16 @@ typedef struct umf_memory_pool_t {
2427

2528
// Memory provider used by the pool.
2629
umf_memory_provider_handle_t provider;
30+
// Tells whether memory provider is owned by the pool.
31+
bool own_provider;
2732
} umf_memory_pool_t;
2833

34+
umf_result_t umfPoolCreateEx(const umf_memory_pool_ops_t *pool_ops,
35+
void *pool_params,
36+
const umf_memory_provider_ops_t *provider_ops,
37+
void *provider_params,
38+
umf_memory_pool_handle_t *hPool);
39+
2940
#ifdef __cplusplus
3041
}
3142
#endif

src/memory_pool_tracking.c

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ umf_result_t umfPoolCreate(const umf_memory_pool_ops_t *ops,
3636
if (ret != UMF_RESULT_SUCCESS) {
3737
goto err_provider_create;
3838
}
39+
pool->own_provider = false;
3940

4041
pool->ops = *ops;
4142
ret = ops->initialize(pool->provider, params, &pool->pool_priv);
@@ -56,6 +57,13 @@ umf_result_t umfPoolCreate(const umf_memory_pool_ops_t *ops,
5657

5758
void umfPoolDestroy(umf_memory_pool_handle_t hPool) {
5859
hPool->ops.finalize(hPool->pool_priv);
60+
if (hPool->own_provider) {
61+
// Destroy associated memory provider.
62+
umf_memory_provider_handle_t hProvider = NULL;
63+
umfPoolGetMemoryProvider(hPool, &hProvider);
64+
umfMemoryProviderDestroy(hProvider);
65+
}
66+
// Destroy tracking provider.
5967
umfMemoryProviderDestroy(hPool->provider);
6068
free(hPool);
6169
}

test/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,7 @@ add_umf_test(NAME memoryPool SRCS memoryPoolAPI.cpp malloc_compliance_tests.cpp
6666
add_umf_test(NAME memoryProvider SRCS memoryProviderAPI.cpp)
6767
add_umf_test(NAME disjointPool SRCS disjoint_pool.cpp malloc_compliance_tests.cpp)
6868
add_umf_test(NAME c_api_disjoint_pool SRCS c_api/disjoint_pool.c)
69+
add_umf_test(NAME memory_pool_internal SRCS memory_pool_internal.cpp)
6970

7071
if(LINUX) # OS-specific functions are implemented only for Linux now
7172
add_umf_test(NAME provider_os_memory SRCS provider_os_memory.cpp LIBS numa)

test/memory_pool_internal.cpp

Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
// Copyright (C) 2023 Intel Corporation
2+
// Under the Apache License v2.0 with LLVM Exceptions. See LICENSE.TXT.
3+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
4+
5+
#include "../src/memory_pool_internal.h"
6+
#include "base.hpp"
7+
#include "common/provider_null.h"
8+
#include "pool.hpp"
9+
#include "provider_trace.h"
10+
#include "test_helpers.h"
11+
12+
#include <unordered_map>
13+
14+
using umf_test::test;
15+
16+
template <typename T> umf_memory_pool_ops_t poolNoParamsMakeCOps() {
17+
umf_memory_pool_ops_t ops = umf::detail::poolOpsBase<T>();
18+
19+
ops.initialize = [](umf_memory_provider_handle_t provider, void *params,
20+
void **obj) {
21+
(void)params;
22+
try {
23+
*obj = new T;
24+
} catch (...) {
25+
return UMF_RESULT_ERROR_OUT_OF_HOST_MEMORY;
26+
}
27+
28+
return umf::detail::initialize<T>(reinterpret_cast<T *>(*obj),
29+
std::make_tuple(provider));
30+
};
31+
32+
return ops;
33+
}
34+
35+
umf_memory_pool_ops_t PROXY_POOL_OPS =
36+
poolNoParamsMakeCOps<umf_test::proxy_pool>();
37+
38+
TEST_F(test, poolCreateExSuccess) {
39+
umf_memory_pool_handle_t pool = nullptr;
40+
auto ret = umfPoolCreateEx(&PROXY_POOL_OPS, nullptr, &UMF_NULL_PROVIDER_OPS,
41+
nullptr, &pool);
42+
ASSERT_EQ(ret, UMF_RESULT_SUCCESS);
43+
ASSERT_NE(pool, nullptr);
44+
45+
umfPoolDestroy(pool);
46+
}
47+
48+
TEST_F(test, poolCreateExNullPoolOps) {
49+
umf_memory_pool_handle_t pool = nullptr;
50+
auto ret = umfPoolCreateEx(nullptr, nullptr, &UMF_NULL_PROVIDER_OPS,
51+
nullptr, &pool);
52+
ASSERT_EQ(ret, UMF_RESULT_ERROR_INVALID_ARGUMENT);
53+
}
54+
55+
TEST_F(test, poolCreateExNullProviderOps) {
56+
umf_memory_pool_handle_t pool = nullptr;
57+
auto ret =
58+
umfPoolCreateEx(&PROXY_POOL_OPS, nullptr, nullptr, nullptr, &pool);
59+
ASSERT_EQ(ret, UMF_RESULT_ERROR_INVALID_ARGUMENT);
60+
}
61+
62+
TEST_F(test, poolCreateExNullPoolHandle) {
63+
auto ret = umfPoolCreateEx(&PROXY_POOL_OPS, nullptr, &UMF_NULL_PROVIDER_OPS,
64+
nullptr, nullptr);
65+
ASSERT_EQ(ret, UMF_RESULT_ERROR_INVALID_ARGUMENT);
66+
}
67+
68+
TEST_F(test, poolCreateExCountProviderCalls) {
69+
auto nullProvider = umf_test::wrapProviderUnique(nullProviderCreate());
70+
71+
static std::unordered_map<std::string, size_t> providerCalls;
72+
auto traceCb = [](const char *name) { providerCalls[name]++; };
73+
74+
umf_provider_trace_params_t provider_params = {nullProvider.get(), traceCb};
75+
76+
umf_memory_pool_handle_t pool = nullptr;
77+
umf_result_t ret =
78+
umfPoolCreateEx(&PROXY_POOL_OPS, nullptr, &UMF_TRACE_PROVIDER_OPS,
79+
&provider_params, &pool);
80+
ASSERT_EQ(ret, UMF_RESULT_SUCCESS);
81+
ASSERT_NE(pool, nullptr);
82+
83+
size_t provider_call_count = 0;
84+
85+
umfPoolMalloc(pool, 0);
86+
ASSERT_EQ(providerCalls["alloc"], 1);
87+
ASSERT_EQ(providerCalls.size(), ++provider_call_count);
88+
89+
umfPoolFree(pool, 0);
90+
ASSERT_EQ(providerCalls["free"], 1);
91+
ASSERT_EQ(providerCalls.size(), ++provider_call_count);
92+
93+
umfPoolCalloc(pool, 0, 0);
94+
ASSERT_EQ(providerCalls["alloc"], 2);
95+
ASSERT_EQ(providerCalls.size(), provider_call_count);
96+
97+
umfPoolAlignedMalloc(pool, 0, 0);
98+
ASSERT_EQ(providerCalls["alloc"], 3);
99+
ASSERT_EQ(providerCalls.size(), provider_call_count);
100+
101+
umfPoolDestroy(pool);
102+
}

0 commit comments

Comments
 (0)