Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
A
Actor Framework
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Operations
Operations
Metrics
Environments
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
cpp-libs
Actor Framework
Commits
7d412701
Commit
7d412701
authored
Oct 23, 2018
by
Dominik Charousset
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Make COW pointer implementation publicly available
parent
9966da79
Changes
9
Hide whitespace changes
Inline
Side-by-side
Showing
9 changed files
with
228 additions
and
112 deletions
+228
-112
libcaf_core/caf/detail/concatenated_tuple.hpp
libcaf_core/caf/detail/concatenated_tuple.hpp
+4
-2
libcaf_core/caf/detail/message_data.hpp
libcaf_core/caf/detail/message_data.hpp
+4
-94
libcaf_core/caf/intrusive_cow_ptr.hpp
libcaf_core/caf/intrusive_cow_ptr.hpp
+200
-0
libcaf_core/src/concatenated_tuple.cpp
libcaf_core/src/concatenated_tuple.cpp
+14
-1
libcaf_core/src/decorated_tuple.cpp
libcaf_core/src/decorated_tuple.cpp
+2
-1
libcaf_core/src/dynamic_message_data.cpp
libcaf_core/src/dynamic_message_data.cpp
+1
-1
libcaf_core/src/mailbox_element.cpp
libcaf_core/src/mailbox_element.cpp
+2
-2
libcaf_core/src/message.cpp
libcaf_core/src/message.cpp
+1
-1
libcaf_core/src/message_data.cpp
libcaf_core/src/message_data.cpp
+0
-10
No files found.
libcaf_core/caf/detail/concatenated_tuple.hpp
View file @
7d412701
...
...
@@ -70,9 +70,11 @@ public:
error
save
(
size_t
pos
,
serializer
&
sink
)
const
override
;
// --
observers -----
---------------------------------------------------------
// --
element access
---------------------------------------------------------
std
::
pair
<
message_data
*
,
size_t
>
select
(
size_t
pos
)
const
;
std
::
pair
<
message_data
*
,
size_t
>
select
(
size_t
pos
);
std
::
pair
<
const
message_data
*
,
size_t
>
select
(
size_t
pos
)
const
;
private:
// -- data members -----------------------------------------------------------
...
...
libcaf_core/caf/detail/message_data.hpp
View file @
7d412701
...
...
@@ -23,10 +23,11 @@
#include <typeinfo>
#include "caf/fwd.hpp"
#include "caf/config.hpp"
#include "caf/ref_counted.hpp"
#include "caf/fwd.hpp"
#include "caf/intrusive_cow_ptr.hpp"
#include "caf/intrusive_ptr.hpp"
#include "caf/ref_counted.hpp"
#include "caf/type_erased_tuple.hpp"
#include "caf/detail/type_list.hpp"
...
...
@@ -38,7 +39,7 @@ class message_data : public ref_counted, public type_erased_tuple {
public:
// -- nested types -----------------------------------------------------------
class
cow_ptr
;
using
cow_ptr
=
intrusive_cow_ptr
<
message_data
>
;
// -- constructors, destructors, and assignment operators --------------------
...
...
@@ -58,97 +59,6 @@ public:
bool
shared
()
const
noexcept
override
;
};
class
message_data
::
cow_ptr
{
public:
// -- constructors, destructors, and assignment operators ------------------
cow_ptr
()
noexcept
=
default
;
cow_ptr
(
cow_ptr
&&
)
noexcept
=
default
;
cow_ptr
(
const
cow_ptr
&
)
noexcept
=
default
;
cow_ptr
&
operator
=
(
cow_ptr
&&
)
noexcept
=
default
;
cow_ptr
&
operator
=
(
const
cow_ptr
&
)
noexcept
=
default
;
template
<
class
T
>
cow_ptr
(
intrusive_ptr
<
T
>
p
)
noexcept
:
ptr_
(
std
::
move
(
p
))
{
// nop
}
inline
cow_ptr
(
message_data
*
ptr
,
bool
add_ref
)
noexcept
:
ptr_
(
ptr
,
add_ref
)
{
// nop
}
// -- modifiers ------------------------------------------------------------
inline
void
swap
(
cow_ptr
&
other
)
noexcept
{
ptr_
.
swap
(
other
.
ptr_
);
}
inline
void
reset
(
message_data
*
p
=
nullptr
,
bool
add_ref
=
true
)
noexcept
{
ptr_
.
reset
(
p
,
add_ref
);
}
inline
message_data
*
release
()
noexcept
{
return
ptr_
.
detach
();
}
inline
void
unshare
()
{
static_cast
<
void
>
(
get_unshared
());
}
inline
message_data
*
operator
->
()
{
return
get_unshared
();
}
inline
message_data
&
operator
*
()
{
return
*
get_unshared
();
}
/// Returns the raw pointer. Callers are responsible for unsharing
/// the content if necessary.
inline
message_data
*
raw_ptr
()
{
return
ptr_
.
get
();
}
// -- observers ------------------------------------------------------------
inline
const
message_data
*
operator
->
()
const
noexcept
{
return
ptr_
.
get
();
}
inline
const
message_data
&
operator
*
()
const
noexcept
{
return
*
ptr_
;
}
inline
explicit
operator
bool
()
const
noexcept
{
return
ptr_
!=
nullptr
;
}
inline
message_data
*
get
()
const
noexcept
{
return
ptr_
.
get
();
}
private:
message_data
*
get_unshared
();
intrusive_ptr
<
message_data
>
ptr_
;
};
inline
bool
operator
==
(
const
message_data
::
cow_ptr
&
x
,
std
::
nullptr_t
)
{
return
x
.
get
()
==
nullptr
;
}
inline
bool
operator
==
(
std
::
nullptr_t
,
const
message_data
::
cow_ptr
&
x
)
{
return
x
.
get
()
==
nullptr
;
}
inline
bool
operator
!=
(
const
message_data
::
cow_ptr
&
x
,
std
::
nullptr_t
)
{
return
x
.
get
()
!=
nullptr
;
}
inline
bool
operator
!=
(
std
::
nullptr_t
,
const
message_data
::
cow_ptr
&
x
)
{
return
x
.
get
()
!=
nullptr
;
}
}
// namespace detail
}
// namespace caf
libcaf_core/caf/intrusive_cow_ptr.hpp
0 → 100644
View file @
7d412701
/******************************************************************************
* ____ _ _____ *
* / ___| / \ | ___| C++ *
* | | / _ \ | |_ Actor *
* | |___ / ___ \| _| Framework *
* \____/_/ \_|_| *
* *
* Copyright 2011-2018 Dominik Charousset *
* *
* Distributed under the terms and conditions of the BSD 3-Clause License or *
* (at your option) under the terms and conditions of the Boost Software *
* License 1.0. See accompanying files LICENSE and LICENSE_ALTERNATIVE. *
* *
* If you did not receive a copy of the license files, see *
* http://opensource.org/licenses/BSD-3-Clause and *
* http://www.boost.org/LICENSE_1_0.txt. *
******************************************************************************/
#pragma once
#include <cstddef>
#include "caf/intrusive_ptr.hpp"
namespace
caf
{
/// An intrusive, reference counting smart pointer implementation with
/// copy-on-write optimization.
/// @relates ref_counted
/// @relates intrusive_ptr
template
<
class
T
>
class
intrusive_cow_ptr
:
detail
::
comparable
<
intrusive_cow_ptr
<
T
>>
,
detail
::
comparable
<
intrusive_cow_ptr
<
T
>
,
T
*>
,
detail
::
comparable
<
intrusive_cow_ptr
<
T
>
,
std
::
nullptr_t
>
,
detail
::
comparable
<
intrusive_cow_ptr
<
T
>
,
intrusive_ptr
<
T
>>
{
public:
// -- member types -----------------------------------------------------------
using
pointer
=
T
*
;
using
const_pointer
=
const
T
*
;
using
element_type
=
T
;
using
reference
=
T
&
;
using
const_reference
=
const
T
&
;
using
counting_pointer
=
intrusive_ptr
<
T
>
;
// -- constructors, destructors, and assignment operators ------------------
intrusive_cow_ptr
()
noexcept
=
default
;
intrusive_cow_ptr
(
intrusive_cow_ptr
&&
)
noexcept
=
default
;
intrusive_cow_ptr
(
const
intrusive_cow_ptr
&
)
noexcept
=
default
;
explicit
intrusive_cow_ptr
(
counting_pointer
p
)
noexcept
:
ptr_
(
std
::
move
(
p
))
{
// nop
}
explicit
intrusive_cow_ptr
(
pointer
ptr
,
bool
add_ref
=
true
)
noexcept
:
ptr_
(
ptr
,
add_ref
)
{
// nop
}
intrusive_cow_ptr
&
operator
=
(
intrusive_cow_ptr
&&
)
noexcept
=
default
;
intrusive_cow_ptr
&
operator
=
(
const
intrusive_cow_ptr
&
)
noexcept
=
default
;
intrusive_cow_ptr
&
operator
=
(
counting_pointer
x
)
noexcept
{
ptr_
=
std
::
move
(
x
);
return
*
this
;
}
// -- comparison -----------------------------------------------------------
ptrdiff_t
compare
(
std
::
nullptr_t
)
const
noexcept
{
return
reinterpret_cast
<
ptrdiff_t
>
(
get
());
}
ptrdiff_t
compare
(
const_pointer
ptr
)
const
noexcept
{
return
static_cast
<
ptrdiff_t
>
(
get
()
-
ptr
);
}
ptrdiff_t
compare
(
const
counting_pointer
&
other
)
const
noexcept
{
return
compare
(
other
.
get
());
}
ptrdiff_t
compare
(
const
intrusive_cow_ptr
&
other
)
const
noexcept
{
return
compare
(
other
.
get
());
}
// -- modifiers ------------------------------------------------------------
/// Swaps the managed object with `other`.
void
swap
(
intrusive_cow_ptr
&
other
)
noexcept
{
ptr_
.
swap
(
other
.
ptr_
);
}
/// Replaces the managed object.
void
reset
(
pointer
p
=
nullptr
,
bool
add_ref
=
true
)
noexcept
{
ptr_
.
reset
(
p
,
add_ref
);
}
/// Returns the raw pointer without modifying reference
/// count and sets this to `nullptr`.
pointer
detach
()
noexcept
{
return
ptr_
.
detach
();
}
/// Returns the raw pointer without modifying reference
/// count and sets this to `nullptr`.
pointer
release
()
noexcept
{
return
ptr_
.
release
();
}
/// Forces a copy of the managed object unless it already has a reference
/// count of exactly 1.
void
unshare
()
{
if
(
ptr_
!=
nullptr
)
static_cast
<
void
>
(
get_unshared
());
}
/// Returns a mutable pointer to the managed object.
pointer
operator
->
()
{
return
get_unshared
();
}
/// Returns a mutable reference to the managed object.
reference
operator
*
()
{
return
*
get_unshared
();
}
/// Returns a mutable pointer to the managed object.
pointer
get_unshared
()
{
auto
p
=
ptr_
.
get
();
if
(
!
p
->
unique
())
{
copy_reset
(
p
->
copy
());
return
ptr_
.
get
();
}
return
p
;
}
// -- observers ------------------------------------------------------------
/// Returns a read-only pointer to the managed object.
const_pointer
get
()
const
noexcept
{
return
ptr_
.
get
();
}
/// Returns the intrusive pointer managing the object.
const
counting_pointer
&
counting_ptr
()
const
noexcept
{
return
ptr_
;
}
/// Returns a read-only pointer to the managed object.
const_pointer
operator
->
()
const
noexcept
{
return
get
();
}
/// Returns a read-only reference to the managed object.
const_reference
operator
*
()
const
noexcept
{
return
*
get
();
}
explicit
operator
bool
()
const
noexcept
{
return
get
()
!=
nullptr
;
}
private:
// -- allow T::copy to return raw, intrusive, or COW pointer -----------------
void
copy_reset
(
pointer
x
)
{
// Reference counted objects start with a reference count of 1.
reset
(
x
,
false
);
}
void
copy_reset
(
counting_pointer
x
)
{
ptr_
.
swap
(
x
);
}
void
copy_reset
(
intrusive_cow_ptr
x
)
{
swap
(
x
);
}
// -- member vairables -------------------------------------------------------
counting_pointer
ptr_
;
};
/// @relates intrusive_cow_ptr
template
<
class
T
>
std
::
string
to_string
(
const
intrusive_cow_ptr
<
T
>&
x
)
{
return
to_string
(
x
.
counting_ptr
());
}
}
// namespace caf
libcaf_core/src/concatenated_tuple.cpp
View file @
7d412701
...
...
@@ -107,7 +107,20 @@ error concatenated_tuple::save(size_t pos, serializer& sink) const {
return
selected
.
first
->
save
(
selected
.
second
,
sink
);
}
std
::
pair
<
message_data
*
,
size_t
>
concatenated_tuple
::
select
(
size_t
pos
)
const
{
std
::
pair
<
message_data
*
,
size_t
>
concatenated_tuple
::
select
(
size_t
pos
)
{
auto
idx
=
pos
;
for
(
auto
&
m
:
data_
)
{
auto
s
=
m
->
size
();
if
(
idx
>=
s
)
idx
-=
s
;
else
return
{
m
.
get_unshared
(),
idx
};
}
CAF_RAISE_ERROR
(
std
::
out_of_range
,
"concatenated_tuple::select out of range"
);
}
std
::
pair
<
const
message_data
*
,
size_t
>
concatenated_tuple
::
select
(
size_t
pos
)
const
{
auto
idx
=
pos
;
for
(
const
auto
&
m
:
data_
)
{
auto
s
=
m
->
size
();
...
...
libcaf_core/src/decorated_tuple.cpp
View file @
7d412701
...
...
@@ -45,7 +45,8 @@ decorated_tuple::cow_ptr decorated_tuple::make(cow_ptr d, vector_type v) {
for
(
auto
&
i
:
v
)
i
=
pmap
[
i
];
}
return
make_counted
<
decorated_tuple
>
(
std
::
move
(
d
),
std
::
move
(
v
));
auto
res
=
make_counted
<
decorated_tuple
>
(
std
::
move
(
d
),
std
::
move
(
v
));
return
decorated_tuple
::
cow_ptr
{
res
};
}
message_data
::
cow_ptr
decorated_tuple
::
copy
()
const
{
...
...
libcaf_core/src/dynamic_message_data.cpp
View file @
7d412701
...
...
@@ -49,7 +49,7 @@ dynamic_message_data::~dynamic_message_data() {
}
message_data
::
cow_ptr
dynamic_message_data
::
copy
()
const
{
return
m
ake_counted
<
dynamic_message_data
>
(
*
this
)
;
return
m
essage_data
::
cow_ptr
{
make_counted
<
dynamic_message_data
>
(
*
this
)}
;
}
void
*
dynamic_message_data
::
get_mutable
(
size_t
pos
)
{
...
...
libcaf_core/src/mailbox_element.cpp
View file @
7d412701
...
...
@@ -42,8 +42,8 @@ public:
:
mailbox_element
(
std
::
move
(
x0
),
dynamic_category_correction
(
x3
,
x1
),
std
::
move
(
x2
)),
msg_
(
std
::
move
(
x3
))
{
/// Make sure that `content` can access the
raw
pointer safely.
if
(
msg_
.
vals
()
.
raw_ptr
()
==
nullptr
)
{
/// Make sure that `content` can access the pointer safely.
if
(
msg_
.
vals
()
==
nullptr
)
{
message_builder
mb
;
msg_
=
mb
.
to_message
();
}
...
...
libcaf_core/src/message.cpp
View file @
7d412701
...
...
@@ -151,7 +151,7 @@ error message::load(deserializer& source) {
err
=
source
.
end_object
();
if
(
err
)
return
err
;
message
result
{
std
::
move
(
dmd
)
};
message
result
{
detail
::
message_data
::
cow_ptr
{
std
::
move
(
dmd
)}
};
swap
(
result
);
return
none
;
}
...
...
libcaf_core/src/message_data.cpp
View file @
7d412701
...
...
@@ -31,15 +31,5 @@ bool message_data::shared() const noexcept {
return
!
unique
();
}
message_data
*
message_data
::
cow_ptr
::
get_unshared
()
{
auto
p
=
ptr_
.
get
();
if
(
!
p
->
unique
())
{
auto
cptr
=
p
->
copy
();
ptr_
.
swap
(
cptr
.
ptr_
);
return
ptr_
.
get
();
}
return
p
;
}
}
// namespace detail
}
// namespace caf
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment