Skip to content
GitLab
Explore
Sign in
Primary navigation
Search or go to…
Project
R
rlib
Manage
Activity
Members
Labels
Plan
Issues
0
Issue boards
Milestones
Wiki
Code
Merge requests
0
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Snippets
Build
Pipelines
Jobs
Pipeline schedules
Artifacts
Deploy
Releases
Package Registry
Model registry
Operate
Environments
Terraform modules
Monitor
Incidents
Analyze
Value stream analytics
Contributor analytics
CI/CD analytics
Repository analytics
Model experiments
Help
Help
Support
GitLab documentation
Compare GitLab plans
Community forum
Contribute to GitLab
Provide feedback
Terms and privacy
Keyboard shortcuts
?
Snippets
Groups
Projects
Show more breadcrumbs
Recolic
rlib
Commits
f14b1940
There was an error fetching the commit references. Please try again later.
Commit
f14b1940
authored
5 years ago
by
Recolic Keghart
Browse files
Options
Downloads
Patches
Plain Diff
fixed passing. TODO: more tests
parent
9fd25a21
No related branches found
No related tags found
No related merge requests found
Changes
4
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
README.md
+3
-1
3 additions, 1 deletion
README.md
pool.hpp
+71
-18
71 additions, 18 deletions
pool.hpp
test/Makefile
+5
-1
5 additions, 1 deletion
test/Makefile
test/src/pool.cc
+53
-0
53 additions, 0 deletions
test/src/pool.cc
with
132 additions
and
20 deletions
README.md
+
3
−
1
View file @
f14b1940
...
@@ -8,6 +8,7 @@ Here is recolic's private library...
...
@@ -8,6 +8,7 @@ Here is recolic's private library...
# TODO
# TODO
```
c++
```
c++
/*
RETEST rlib::noncopyable
RETEST rlib::noncopyable
rlib::stdio fd control is still a problem.
rlib::stdio fd control is still a problem.
...
@@ -17,4 +18,5 @@ rlib::meta::array::to_tuple
...
@@ -17,4 +18,5 @@ rlib::meta::array::to_tuple
rlib::meta::string
rlib::meta::string
#DONE#rlib::logger
#DONE#rlib::logger
```
*/
```
\ No newline at end of file
This diff is collapsed.
Click to expand it.
pool.hpp
+
71
−
18
View file @
f14b1940
...
@@ -7,6 +7,7 @@
...
@@ -7,6 +7,7 @@
#include
<tuple>
#include
<tuple>
#include
<functional>
#include
<functional>
#include
<algorithm>
#include
<algorithm>
#include
<atomic>
#ifdef RLIB_SWITCH_USE_MINGW_THREAD_FIX
#ifdef RLIB_SWITCH_USE_MINGW_THREAD_FIX
#include
<mingw.mutex.h>
#include
<mingw.mutex.h>
...
@@ -17,29 +18,75 @@
...
@@ -17,29 +18,75 @@
#include
<mutex>
#include
<mutex>
#include
<condition_variable>
#include
<condition_variable>
#endif
#endif
using
size_t
=
unsigned
long
;
namespace
rlib
{
namespace
rlib
{
struct
object_pool_policy_fixed
{
object_pool_policy_fixed
(
size_t
size
)
:
size
(
size
),
used
(
new
std
::
atomic
<
size_t
>
(
0
))
{}
bool
borrow_should_alloc
(
/*const size_t free_objects, const size_t existing_objects*/
)
{
// TODO: add size argument?
// object_pool::borrow calls this funcion.
// If it returns true, object pool will alloc a new object.
// If it returns false, object pool will not alloc a new object.
// If it returns false, THIS FUNCTION MUST HAVE NO SIDE EFFECT!
// If there's no free object, object pool::borrow blocks.
while
(
true
)
{
auto
used_old
=
used
->
load
(
std
::
memory_order_acquire
);
if
(
used_old
>=
size
)
{
return
false
;
}
auto
used_new
=
used_old
+
1
;
if
(
used
->
compare_exchange_strong
(
used_old
,
used_new
,
std
::
memory_order_acq_rel
))
break
;
// success
}
return
true
;
}
bool
release_should_free
()
{
if
(
used
->
load
()
==
0
)
throw
std
::
runtime_error
(
"POLICY detected error: Release object of zero-sized object pool."
);
(
*
used
)
--
;
return
false
;
}
private
:
const
size_t
size
;
std
::
unique_ptr
<
std
::
atomic
<
size_t
>
>
used
;
};
struct
object_pool_policy_dynamic_never_free
{
object_pool_policy_dynamic_never_free
()
:
fixed
(
std
::
numeric_limits
<
size_t
>::
max
())
{}
bool
borrow_should_alloc
()
{
return
fixed
.
borrow_should_alloc
();
}
bool
release_should_free
()
{
return
fixed
.
release_should_free
();
}
private
:
object_pool_policy_fixed
fixed
;
};
struct
object_pool_policy_dynamic_smart
{
};
/*
/*
* Multi-threaded object_pool. It will block current thread and wait if
* Multi-threaded object_pool. It will block current thread and wait if
* borrow_one() starves, until some other threads release their obj.
* borrow_one() starves, until some other threads release their obj.
*/
*/
template
<
typename
obj_t
,
typename
...
_bound_construct_args_t
>
template
<
typename
policy_t
,
typename
obj_t
,
typename
...
_bound_construct_args_t
>
class
fixed_
object_pool
:
rlib
::
nonmovable
{
class
object_pool
:
rlib
::
nonmovable
{
protected:
protected:
using
element_t
=
obj_t
;
using
element_t
=
obj_t
;
using
buffer_t
=
impl
::
traceable_list
<
obj_t
,
bool
>
;
using
buffer_t
=
impl
::
traceable_list
<
obj_t
,
bool
>
;
using
this_type
=
fixed_
object_pool
<
obj_t
,
_bound_construct_args_t
...
>
;
using
this_type
=
object_pool
<
obj_t
,
_bound_construct_args_t
...
>
;
public:
public:
explicit
fixed_object_pool
(
size_t
max_size
,
_bound_construct_args_t
...
_args
)
object_pool
()
=
delete
;
:
max_size
(
max_size
),
_bound_args
(
std
::
forward
<
_bound_construct_args_t
>
(
_args
)
...)
explicit
object_pool
(
policy_t
&&
policy
,
_bound_construct_args_t
...
_args
)
:
policy
(
std
::
forward
<
policy_t
>
(
policy
)),
_bound_args
(
std
::
forward
<
_bound_construct_args_t
>
(
_args
)
...)
{}
{}
void
fill_full
()
{
//
void fill_full() {
for
(
size_t
cter
=
0
;
cter
<
max_size
;
++
cter
)
{
//
for (size_t cter = 0; cter < max_size; ++cter) {
new_obj_to_buffer
();
//
new_obj_to_buffer();
free_list
.
push_back
(
&*--
buffer
.
end
());
//
free_list.push_back(&*--buffer.end());
}
//
}
}
//
}
// `new` an object. Return nullptr if pool is full.
// `new` an object. Return nullptr if pool is full.
obj_t
*
try_borrow_one
()
{
obj_t
*
try_borrow_one
()
{
...
@@ -53,6 +100,7 @@ namespace rlib {
...
@@ -53,6 +100,7 @@ namespace rlib {
// Not available. Wait for release_one.
// Not available. Wait for release_one.
std
::
unique_lock
<
std
::
mutex
>
lk
(
buffer_mutex
);
std
::
unique_lock
<
std
::
mutex
>
lk
(
buffer_mutex
);
// wait for a release
borrow_cv
.
wait
(
lk
,
[
this
]{
return
this
->
new_obj_ready
;});
borrow_cv
.
wait
(
lk
,
[
this
]{
return
this
->
new_obj_ready
;});
result
=
do_try_borrow_one
();
result
=
do_try_borrow_one
();
...
@@ -76,12 +124,17 @@ namespace rlib {
...
@@ -76,12 +124,17 @@ namespace rlib {
reconstruct_impl
(
which
,
std
::
make_index_sequence
<
sizeof
...(
_bound_construct_args_t
)
>
());
reconstruct_impl
(
which
,
std
::
make_index_sequence
<
sizeof
...(
_bound_construct_args_t
)
>
());
}
}
size_t
size
()
const
{
return
curr_size
;
}
protected
:
protected
:
buffer_t
buffer
;
// list<obj_t obj, bool is_free>
buffer_t
buffer
;
// list<obj_t obj, bool is_free>
private
:
private
:
std
::
tuple
<
_bound_construct_args_t
...
>
_bound_args
;
std
::
tuple
<
_bound_construct_args_t
...
>
_bound_args
;
size_t
max_size
;
size_t
curr_size
=
0
;
policy_t
policy
;
std
::
list
<
obj_t
*>
free_list
;
std
::
list
<
obj_t
*>
free_list
;
std
::
mutex
buffer_mutex
;
std
::
mutex
buffer_mutex
;
std
::
condition_variable
borrow_cv
;
std
::
condition_variable
borrow_cv
;
...
@@ -90,7 +143,11 @@ namespace rlib {
...
@@ -90,7 +143,11 @@ namespace rlib {
// try_borrow_one without lock.
// try_borrow_one without lock.
obj_t
*
do_try_borrow_one
()
{
obj_t
*
do_try_borrow_one
()
{
// Optimize here if is performance bottleneck (lockless list... etc...)
// Optimize here if is performance bottleneck (lockless list... etc...)
borrow_again:
// NOT THREAD SAFE. USE buffer_mutex.
if
(
policy
.
borrow_should_alloc
())
{
new_obj_to_buffer
();
free_list
.
push_back
(
&*--
buffer
.
end
());
}
if
(
free_list
.
size
()
>
0
)
{
if
(
free_list
.
size
()
>
0
)
{
// Some object is free. Just return one.
// Some object is free. Just return one.
obj_t
*
result
=
*
free_list
.
begin
();
obj_t
*
result
=
*
free_list
.
begin
();
...
@@ -99,13 +156,9 @@ namespace rlib {
...
@@ -99,13 +156,9 @@ namespace rlib {
typename
buffer_t
::
iterator
elem_iter
(
result
);
typename
buffer_t
::
iterator
elem_iter
(
result
);
elem_iter
.
get_extra_info
()
=
false
;
// mark as busy.
elem_iter
.
get_extra_info
()
=
false
;
// mark as busy.
new_obj_ready
=
false
;
new_obj_ready
=
false
;
++
curr_size
;
return
result
;
return
result
;
}
}
if
(
buffer
.
size
()
<
max_size
)
{
new_obj_to_buffer
();
free_list
.
push_back
(
&*--
buffer
.
end
());
goto
borrow_again
;
}
return
nullptr
;
return
nullptr
;
}
}
...
...
This diff is collapsed.
Click to expand it.
test/Makefile
+
5
−
1
View file @
f14b1940
...
@@ -40,7 +40,7 @@ endif
...
@@ -40,7 +40,7 @@ endif
POSTFIX
=
$(
STD
)
_
$(
CXX
)
POSTFIX
=
$(
STD
)
_
$(
CXX
)
all
:
string common
all
:
string common
pool
common
:
common
:
$(
CXX
)
$(
CXXFLAGS
)
src/common.cc
$(
CXXFLAGS
)
-o
src/common_
$(
POSTFIX
)
.out
$(
CXX
)
$(
CXXFLAGS
)
src/common.cc
$(
CXXFLAGS
)
-o
src/common_
$(
POSTFIX
)
.out
...
@@ -50,6 +50,10 @@ string:
...
@@ -50,6 +50,10 @@ string:
$(
CXX
)
$(
CXXFLAGS
)
src/string.cc
$(
CXXFLAGS
)
-o
src/string_
$(
POSTFIX
)
.out
$(
CXX
)
$(
CXXFLAGS
)
src/string.cc
$(
CXXFLAGS
)
-o
src/string_
$(
POSTFIX
)
.out
src/string_
$(
POSTFIX
)
.out
src/string_
$(
POSTFIX
)
.out
pool
:
$(
CXX
)
$(
CXXFLAGS
)
src/pool.cc
$(
CXXFLAGS
)
-o
src/pool_
$(
POSTFIX
)
.out
src/pool_
$(
POSTFIX
)
.out
clean
:
clean
:
rm
-f
src/
*
.out
rm
-f
src/
*
.out
...
...
This diff is collapsed.
Click to expand it.
test/src/pool.cc
0 → 100644
+
53
−
0
View file @
f14b1940
#define CATCH_CONFIG_MAIN
#include
<catch.hpp>
#include
<rlib/pool.hpp>
#include
<string>
using
std
::
string
;
struct
pooled_obj_t
{
pooled_obj_t
(
int
arg1
,
string
arg2
)
:
arg1
(
arg1
),
arg2
(
arg2
)
{}
pooled_obj_t
(
const
pooled_obj_t
&
another
)
=
delete
;
pooled_obj_t
()
=
delete
;
int
arg1
;
string
arg2
;
};
TEST_CASE
(
"fixed object pool"
)
{
size_t
pool_size
=
8
;
const
auto
arg1
=
666
;
const
auto
arg2
=
string
(
"fuck you"
);
rlib
::
object_pool
<
rlib
::
object_pool_policy_fixed
,
pooled_obj_t
,
int
,
string
>
fixed_pool
(
rlib
::
object_pool_policy_fixed
(
pool_size
),
arg1
,
arg2
);
auto
res
=
fixed_pool
.
try_borrow_one
();
REQUIRE
(
res
!=
nullptr
);
REQUIRE
(
res
->
arg1
==
arg1
);
REQUIRE
(
res
->
arg2
==
arg2
);
size_t
test_rounds
=
1024
;
for
(
auto
_
=
0
;
_
<
test_rounds
;
++
_
)
{
std
::
list
<
decltype
(
res
)
>
objs
;
for
(
auto
cter
=
0
;
cter
<
pool_size
-
1
;
++
cter
)
{
auto
ptr
=
fixed_pool
.
try_borrow_one
();
REQUIRE
(
ptr
!=
nullptr
);
REQUIRE
(
ptr
->
arg2
==
arg2
);
fixed_pool
.
reconstruct_one
(
ptr
);
REQUIRE
(
ptr
->
arg2
==
arg2
);
objs
.
push_back
(
ptr
);
}
REQUIRE
(
fixed_pool
.
try_borrow_one
()
==
nullptr
);
REQUIRE
(
fixed_pool
.
try_borrow_one
()
==
nullptr
);
for
(
auto
cter
=
0
;
cter
<
pool_size
-
1
;
++
cter
)
{
fixed_pool
.
release_one
(
*
objs
.
begin
());
objs
.
pop_front
();
}
}
}
This diff is collapsed.
Click to expand it.
Preview
0%
Loading
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Save comment
Cancel
Please
register
or
sign in
to comment