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
2cbd028b
Commit
2cbd028b
authored
Nov 27, 2017
by
Dominik Charousset
Committed by
Dominik Charousset
Feb 06, 2018
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Revise message_id and add intrusive containers
parent
1feb1109
Changes
15
Show whitespace changes
Inline
Side-by-side
Showing
15 changed files
with
724 additions
and
151 deletions
+724
-151
libcaf_core/caf/detail/single_reader_queue.hpp
libcaf_core/caf/detail/single_reader_queue.hpp
+34
-8
libcaf_core/caf/detail/unordered_flat_map.hpp
libcaf_core/caf/detail/unordered_flat_map.hpp
+289
-0
libcaf_core/caf/intrusive/bidirectional_iterator.hpp
libcaf_core/caf/intrusive/bidirectional_iterator.hpp
+140
-0
libcaf_core/caf/intrusive/doubly_linked.hpp
libcaf_core/caf/intrusive/doubly_linked.hpp
+68
-0
libcaf_core/caf/intrusive/partitioned_list.hpp
libcaf_core/caf/intrusive/partitioned_list.hpp
+30
-72
libcaf_core/caf/logger.hpp
libcaf_core/caf/logger.hpp
+18
-7
libcaf_core/caf/mailbox_element.hpp
libcaf_core/caf/mailbox_element.hpp
+9
-11
libcaf_core/caf/message_id.hpp
libcaf_core/caf/message_id.hpp
+108
-32
libcaf_core/caf/message_priority.hpp
libcaf_core/caf/message_priority.hpp
+1
-1
libcaf_core/caf/scheduled_actor.hpp
libcaf_core/caf/scheduled_actor.hpp
+3
-3
libcaf_core/src/logger.cpp
libcaf_core/src/logger.cpp
+17
-6
libcaf_core/src/mailbox_element.cpp
libcaf_core/src/mailbox_element.cpp
+2
-7
libcaf_core/src/stream_gatherer_impl.cpp
libcaf_core/src/stream_gatherer_impl.cpp
+2
-0
libcaf_core/test/logger.cpp
libcaf_core/test/logger.cpp
+0
-2
libcaf_io/caf/io/abstract_broker.hpp
libcaf_io/caf/io/abstract_broker.hpp
+3
-2
No files found.
libcaf_core/caf/detail/single_reader_queue.hpp
View file @
2cbd028b
...
...
@@ -29,7 +29,7 @@
#include <limits>
#include <condition_variable> // std::cv_status
#include "caf/
detail/intrusive_
partitioned_list.hpp"
#include "caf/
intrusive/
partitioned_list.hpp"
namespace
caf
{
namespace
detail
{
...
...
@@ -54,10 +54,14 @@ template <class T, class Delete = std::default_delete<T>>
class
single_reader_queue
{
public:
using
value_type
=
T
;
using
pointer
=
value_type
*
;
using
deleter_type
=
Delete
;
using
unique_pointer
=
std
::
unique_ptr
<
value_type
,
deleter_type
>
;
using
cache_type
=
intrusive_partitioned_list
<
value_type
,
deleter_type
>
;
using
cache_type
=
intrusive
::
partitioned_list
<
value_type
,
deleter_type
>
;
/// Tries to dequeue a new element from the mailbox.
/// @warning Call only from the reader (owner).
...
...
@@ -162,12 +166,17 @@ public:
fetch_new_data
();
auto
ptr
=
head_
;
while
(
ptr
&&
res
<
max_count
)
{
ptr
=
p
tr
->
next
;
ptr
=
p
romote
(
ptr
->
next
)
;
++
res
;
}
return
res
;
}
void
prepend
(
pointer
ptr
)
{
ptr
->
next
=
head_
;
head_
=
ptr
;
}
pointer
peek
()
{
if
(
head_
!=
nullptr
||
fetch_new_data
())
return
head_
;
...
...
@@ -195,7 +204,7 @@ public:
auto
tail
=
old_head
;
while
(
tail
->
next
!=
nullptr
)
tail
=
tail
->
next
;
// This gets new data from the stack and rewrite head_.
// This gets new data from the stack and rewrite
s
head_.
fetch_new_data
();
tail
->
next
=
head_
;
head_
=
old_head
;
...
...
@@ -265,6 +274,23 @@ public:
return
true
;
}
/// Take the stack pointer without re-ordering it to the cache.
pointer
take_stack
()
{
auto
end_ptr
=
stack_empty_dummy
();
pointer
e
=
stack_
.
load
();
// must not be called on a closed queue
CAF_ASSERT
(
e
!=
nullptr
);
// fetching data while blocked is an error
CAF_ASSERT
(
e
!=
reader_blocked_dummy
());
// it's enough to check this once, since only the owner is allowed
// to close the queue and only the owner is allowed to call this
// member function
while
(
e
!=
end_ptr
)
if
(
stack_
.
compare_exchange_weak
(
e
,
end_ptr
))
return
e
;
return
nullptr
;
}
private:
// exposed to "outside" access
std
::
atomic
<
pointer
>
stack_
;
...
...
@@ -272,7 +298,7 @@ private:
// accessed only by the owner
pointer
head_
;
deleter_type
delete_
;
intrusive
_
partitioned_list
<
value_type
,
deleter_type
>
cache_
;
intrusive
::
partitioned_list
<
value_type
,
deleter_type
>
cache_
;
// atomically sets stack_ back and enqueues all elements to the cache
bool
fetch_new_data
(
pointer
end_ptr
)
{
...
...
@@ -299,7 +325,7 @@ private:
auto
next
=
e
->
next
;
e
->
next
=
head_
;
head_
=
e
;
e
=
next
;
e
=
promote
(
next
)
;
}
return
true
;
}
...
...
@@ -315,7 +341,7 @@ private:
pointer
take_head
()
{
if
(
head_
!=
nullptr
||
fetch_new_data
())
{
auto
result
=
head_
;
head_
=
head_
->
next
;
head_
=
promote
(
head_
->
next
)
;
return
result
;
}
return
nullptr
;
...
...
@@ -324,7 +350,7 @@ private:
template
<
class
F
>
void
clear_cached_elements
(
const
F
&
f
)
{
while
(
head_
)
{
auto
next
=
head_
->
next
;
auto
next
=
promote
(
head_
->
next
)
;
f
(
*
head_
);
delete_
(
head_
);
head_
=
next
;
...
...
libcaf_core/caf/detail/unordered_flat_map.hpp
0 → 100644
View file @
2cbd028b
/******************************************************************************
* ____ _ _____ *
* / ___| / \ | ___| C++ *
* | | / _ \ | |_ Actor *
* | |___ / ___ \| _| Framework *
* \____/_/ \_|_| *
* *
* Copyright (C) 2011 - 2017 *
* Dominik Charousset <dominik.charousset (at) haw-hamburg.de> *
* *
* 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. *
******************************************************************************/
#ifndef CAF_DETAIL_UNORDERED_FLAT_MAP_HPP
#define CAF_DETAIL_UNORDERED_FLAT_MAP_HPP
#include <vector>
#include <algorithm>
#include <stdexcept>
#include <functional>
#include "caf/detail/comparable.hpp"
namespace
caf
{
namespace
detail
{
/// A map abstraction with an unsorted `std::vector` providing `O(n)` lookup.
template
<
class
Key
,
class
T
,
class
Allocator
=
std
::
allocator
<
std
::
pair
<
Key
,
T
>
>>
class
unordered_flat_map
{
public:
// -- member types ----------------------------------------------------------
using
key_type
=
Key
;
using
mapped_type
=
T
;
using
value_type
=
std
::
pair
<
Key
,
T
>
;
using
vector_type
=
std
::
vector
<
value_type
,
Allocator
>
;
using
allocator_type
=
typename
vector_type
::
allocator_type
;
using
size_type
=
typename
vector_type
::
size_type
;
using
difference_type
=
typename
vector_type
::
difference_type
;
using
reference
=
typename
vector_type
::
reference
;
using
const_reference
=
typename
vector_type
::
const_reference
;
using
pointer
=
typename
vector_type
::
pointer
;
using
const_pointer
=
typename
vector_type
::
const_pointer
;
using
iterator
=
typename
vector_type
::
iterator
;
using
const_iterator
=
typename
vector_type
::
const_iterator
;
using
reverse_iterator
=
typename
vector_type
::
reverse_iterator
;
using
const_reverse_iterator
=
typename
vector_type
::
const_reverse_iterator
;
// -- constructors, destructors, and assignment operators -------------------
unordered_flat_map
()
=
default
;
unordered_flat_map
(
std
::
initializer_list
<
value_type
>
l
)
:
xs_
(
l
)
{
// nop
}
template
<
class
InputIterator
>
unordered_flat_map
(
InputIterator
first
,
InputIterator
last
)
:
xs_
(
first
,
last
)
{
// nop
}
// -- non-const begin iterators ---------------------------------------------
iterator
begin
()
{
return
xs_
.
begin
();
}
reverse_iterator
rbegin
()
{
return
xs_
.
rbegin
();
}
// -- const begin iterators -------------------------------------------------
const_iterator
begin
()
const
{
return
xs_
.
begin
();
}
const_iterator
cbegin
()
const
{
return
xs_
.
cbegin
();
}
const_reverse_iterator
rbegin
()
const
{
return
xs_
.
rbegin
();
}
// -- non-const end iterators -----------------------------------------------
iterator
end
()
{
return
xs_
.
end
();
}
reverse_iterator
rend
()
{
return
xs_
.
rend
();
}
// -- const end iterators ---------------------------------------------------
const_iterator
end
()
const
{
return
xs_
.
end
();
}
const_iterator
cend
()
const
{
return
xs_
.
end
();
}
const_reverse_iterator
rend
()
const
{
return
xs_
.
rend
();
}
// -- capacity --------------------------------------------------------------
bool
empty
()
const
{
return
xs_
.
empty
();
}
size_type
size
()
const
{
return
xs_
.
size
();
}
void
reserve
(
size_type
count
)
{
xs_
.
reserve
(
count
);
}
void
shrink_to_fit
()
{
xs_
.
shrink_to_fit
();
}
// -- modifiers -------------------------------------------------------------
void
clear
()
{
return
xs_
.
clear
();
}
std
::
pair
<
iterator
,
bool
>
insert
(
value_type
x
)
{
return
insert
(
end
(),
std
::
move
(
x
));
}
std
::
pair
<
iterator
,
bool
>
insert
(
iterator
hint
,
value_type
x
)
{
return
insert
(
static_cast
<
const_iterator
>
(
hint
),
std
::
move
(
x
));
}
std
::
pair
<
iterator
,
bool
>
insert
(
const_iterator
hint
,
value_type
x
)
{
auto
i
=
find
(
x
.
first
);
if
(
i
==
end
())
return
{
xs_
.
insert
(
hint
,
std
::
move
(
x
)),
true
};
return
{
i
,
false
};
}
template
<
class
InputIterator
>
void
insert
(
InputIterator
first
,
InputIterator
last
)
{
while
(
first
!=
last
)
insert
(
*
first
++
);
}
template
<
class
...
Ts
>
std
::
pair
<
iterator
,
bool
>
emplace
(
Ts
&&
...
xs
)
{
return
emplace_hint
(
end
(),
std
::
forward
<
Ts
>
(
xs
)...);
}
template
<
class
...
Ts
>
std
::
pair
<
iterator
,
bool
>
emplace_hint
(
const_iterator
hint
,
Ts
&&
...
xs
)
{
return
insert
(
hint
,
value_type
(
std
::
forward
<
Ts
>
(
xs
)...));
}
iterator
erase
(
const_iterator
i
)
{
return
xs_
.
erase
(
i
);
}
iterator
erase
(
const_iterator
first
,
const_iterator
last
)
{
return
xs_
.
erase
(
first
,
last
);
}
size_type
erase
(
const
key_type
&
x
)
{
auto
pred
=
[
&
](
const
value_type
&
y
)
{
return
x
==
y
.
first
;
};
auto
i
=
std
::
remove_if
(
begin
(),
end
(),
pred
);
if
(
i
==
end
())
return
0
;
erase
(
i
);
return
1
;
}
void
swap
(
unordered_flat_map
&
other
)
{
xs_
.
swap
(
other
);
}
// -- lookup ----------------------------------------------------------------
template
<
class
K
>
mapped_type
&
at
(
const
K
&
key
)
{
auto
i
=
find
(
key
);
if
(
i
==
end
())
throw
std
::
out_of_range
{
"caf::detail::unordered_flat_map::at"
};
return
i
->
second
;
}
template
<
class
K
>
const
mapped_type
&
at
(
const
K
&
key
)
const
{
auto
i
=
find
(
key
);
if
(
i
==
end
())
throw
std
::
out_of_range
{
"caf::detail::unordered_flat_map::at"
};
return
i
->
second
;
}
mapped_type
&
operator
[](
const
key_type
&
key
)
{
auto
i
=
find
(
key
);
if
(
i
!=
end
())
return
i
->
second
;
return
xs_
.
insert
(
i
,
value_type
{
key
,
mapped_type
{}})
->
second
;
}
template
<
class
K
>
iterator
find
(
const
K
&
x
)
{
auto
pred
=
[
&
](
const
value_type
&
y
)
{
return
x
==
y
.
first
;
};
return
std
::
find_if
(
xs_
.
begin
(),
xs_
.
end
(),
pred
);
}
template
<
class
K
>
const_iterator
find
(
const
K
&
x
)
const
{
auto
pred
=
[
&
](
const
value_type
&
y
)
{
return
x
==
y
.
first
;
};
return
std
::
find_if
(
xs_
.
begin
(),
xs_
.
end
(),
pred
);
}
template
<
class
K
>
size_type
count
(
const
K
&
x
)
const
{
return
find
(
x
)
==
end
()
?
0
:
1
;
}
private:
vector_type
xs_
;
};
template
<
class
K
,
class
T
,
class
A
>
bool
operator
==
(
const
unordered_flat_map
<
K
,
T
,
A
>&
xs
,
const
unordered_flat_map
<
K
,
T
,
A
>&
ys
)
{
return
xs
.
size
()
==
ys
.
size
()
&&
std
::
equal
(
xs
.
begin
(),
xs
.
end
(),
ys
.
begin
());
}
template
<
class
K
,
class
T
,
class
A
>
bool
operator
!=
(
const
unordered_flat_map
<
K
,
T
,
A
>&
xs
,
const
unordered_flat_map
<
K
,
T
,
A
>&
ys
)
{
return
!
(
xs
==
ys
);
}
template
<
class
K
,
class
T
,
class
A
>
bool
operator
<
(
const
unordered_flat_map
<
K
,
T
,
A
>&
xs
,
const
unordered_flat_map
<
K
,
T
,
A
>&
ys
)
{
return
std
::
lexicographical_compare
(
xs
.
begin
(),
xs
.
end
(),
ys
.
begin
(),
ys
.
end
());
}
template
<
class
K
,
class
T
,
class
A
>
bool
operator
>=
(
const
unordered_flat_map
<
K
,
T
,
A
>&
xs
,
const
unordered_flat_map
<
K
,
T
,
A
>&
ys
)
{
return
!
(
xs
<
ys
);
}
}
// namespace detail
}
// namespace caf
#endif // CAF_DETAIL_UNORDERED_FLAT_MAP_HPP
libcaf_core/caf/intrusive/bidirectional_iterator.hpp
0 → 100644
View file @
2cbd028b
/******************************************************************************
* ____ _ _____ *
* / ___| / \ | ___| C++ *
* | | / _ \ | |_ Actor *
* | |___ / ___ \| _| Framework *
* \____/_/ \_|_| *
* *
* Copyright (C) 2011 - 2017 *
* Dominik Charousset <dominik.charousset (at) haw-hamburg.de> *
* *
* 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. *
******************************************************************************/
#ifndef CAF_INTRUSIVE_BIDIRECTIONAL_ITERATOR_HPP
#define CAF_INTRUSIVE_BIDIRECTIONAL_ITERATOR_HPP
#include <cstddef>
#include <iterator>
#include <type_traits>
#include "caf/intrusive/doubly_linked.hpp"
namespace
caf
{
namespace
intrusive
{
/// Intrusive base for doubly linked types that allows queues to use `T` with
/// node nodes.
template
<
class
T
>
class
bidirectional_iterator
{
public:
// -- member types -----------------------------------------------------------
using
difference_type
=
std
::
ptrdiff_t
;
using
value_type
=
T
;
using
pointer
=
value_type
*
;
using
const_pointer
=
const
value_type
*
;
using
reference
=
value_type
&
;
using
const_reference
=
const
value_type
&
;
using
node_type
=
typename
std
::
conditional
<
std
::
is_const
<
T
>::
value
,
const
typename
T
::
node_type
,
typename
T
::
node_type
>::
type
;
using
node_pointer
=
node_type
*
;
using
iterator_category
=
std
::
bidirectional_iterator_tag
;
// -- member variables -------------------------------------------------------
node_pointer
ptr
;
// -- constructors, destructors, and assignment operators --------------------
constexpr
bidirectional_iterator
(
node_pointer
init
=
nullptr
)
:
ptr
(
init
)
{
// nop
}
bidirectional_iterator
(
const
bidirectional_iterator
&
)
=
default
;
bidirectional_iterator
&
operator
=
(
const
bidirectional_iterator
&
)
=
default
;
// -- convenience functions --------------------------------------------------
bidirectional_iterator
next
()
{
return
ptr
->
next
;
}
// -- operators --------------------------------------------------------------
bidirectional_iterator
&
operator
++
()
{
ptr
=
promote
(
ptr
->
next
);
return
*
this
;
}
bidirectional_iterator
operator
++
(
int
)
{
bidirectional_iterator
res
=
*
this
;
ptr
=
promote
(
ptr
->
next
);
return
res
;
}
bidirectional_iterator
&
operator
--
()
{
ptr
=
ptr
->
prev
;
return
*
this
;
}
bidirectional_iterator
operator
--
(
int
)
{
bidirectional_iterator
res
=
*
this
;
ptr
=
promote
(
ptr
->
prev
);
return
res
;
}
reference
operator
*
()
{
return
*
promote
(
ptr
);
}
const_reference
operator
*
()
const
{
return
*
promote
(
ptr
);
}
pointer
operator
->
()
{
return
promote
(
ptr
);
}
const
pointer
operator
->
()
const
{
return
promote
(
ptr
);
}
};
/// @relates bidirectional_iterator
template
<
class
T
>
bool
operator
==
(
const
bidirectional_iterator
<
T
>&
x
,
const
bidirectional_iterator
<
T
>&
y
)
{
return
x
.
ptr
==
y
.
ptr
;
}
/// @relates bidirectional_iterator
template
<
class
T
>
bool
operator
!=
(
const
bidirectional_iterator
<
T
>&
x
,
const
bidirectional_iterator
<
T
>&
y
)
{
return
x
.
ptr
!=
y
.
ptr
;
}
}
// namespace intrusive
}
// namespace caf
#endif // CAF_INTRUSIVE_BIDIRECTIONAL_ITERATOR_HPP
libcaf_core/caf/intrusive/doubly_linked.hpp
0 → 100644
View file @
2cbd028b
/******************************************************************************
* ____ _ _____ *
* / ___| / \ | ___| C++ *
* | | / _ \ | |_ Actor *
* | |___ / ___ \| _| Framework *
* \____/_/ \_|_| *
* *
* Copyright (C) 2011 - 2017 *
* Dominik Charousset <dominik.charousset (at) haw-hamburg.de> *
* *
* 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. *
******************************************************************************/
#ifndef CAF_INTRUSIVE_DOUBLY_LINKED_HPP
#define CAF_INTRUSIVE_DOUBLY_LINKED_HPP
namespace
caf
{
namespace
intrusive
{
/// Intrusive base for doubly linked types that allows queues to use `T` with
/// dummy nodes.
template
<
class
T
>
struct
doubly_linked
{
// -- member types -----------------------------------------------------------
/// The type for dummy nodes in doubly linked lists.
using
node_type
=
doubly_linked
<
T
>
;
/// Type of the pointer connecting two doubly linked nodes.
using
node_pointer
=
node_type
*
;
// -- constructors, destructors, and assignment operators --------------------
doubly_linked
(
node_pointer
n
=
nullptr
,
node_pointer
p
=
nullptr
)
:
next
(
n
),
prev
(
p
)
{
// nop
}
// -- member variables -------------------------------------------------------
/// Intrusive pointer to the next element.
node_pointer
next
;
/// Intrusive pointer to the previous element.
node_pointer
prev
;
};
template
<
class
T
>
T
*
promote
(
doubly_linked
<
T
>*
ptr
)
{
return
static_cast
<
T
*>
(
ptr
);
}
template
<
class
T
>
const
T
*
promote
(
const
doubly_linked
<
T
>*
ptr
)
{
return
static_cast
<
const
T
*>
(
ptr
);
}
}
// namespace intrusive
}
// namespace caf
#endif // CAF_INTRUSIVE_DOUBLY_LINKED_HPP
libcaf_core/caf/
detail/intrusive_
partitioned_list.hpp
→
libcaf_core/caf/
intrusive/
partitioned_list.hpp
View file @
2cbd028b
...
...
@@ -16,8 +16,8 @@
* http://www.boost.org/LICENSE_1_0.txt. *
******************************************************************************/
#ifndef CAF_
DETAIL_
INTRUSIVE_PARTITIONED_LIST_HPP
#define CAF_
DETAIL_
INTRUSIVE_PARTITIONED_LIST_HPP
#ifndef CAF_INTRUSIVE_PARTITIONED_LIST_HPP
#define CAF_INTRUSIVE_PARTITIONED_LIST_HPP
#include "caf/config.hpp"
...
...
@@ -28,8 +28,11 @@
#include "caf/behavior.hpp"
#include "caf/invoke_message_result.hpp"
#include "caf/intrusive/doubly_linked.hpp"
#include "caf/intrusive/bidirectional_iterator.hpp"
namespace
caf
{
namespace
detail
{
namespace
intrusive
{
/// Describes a partitioned list of elements. The first part
/// of the list is described by the iterator pair `[begin, separator)`.
...
...
@@ -37,82 +40,39 @@ namespace detail {
/// of the list to store previously skipped elements. Priority-aware actors
/// also use the first half of the list to sort messages by priority.
template
<
class
T
,
class
Delete
=
std
::
default_delete
<
T
>
>
class
intrusive_
partitioned_list
{
class
partitioned_list
{
public:
using
value_type
=
T
;
using
pointer
=
value_type
*
;
using
deleter_type
=
Delete
;
struct
iterator
:
std
::
iterator
<
std
::
bidirectional_iterator_tag
,
value_type
>
{
pointer
ptr
;
iterator
(
pointer
init
=
nullptr
)
:
ptr
(
init
)
{
// nop
}
iterator
(
const
iterator
&
)
=
default
;
iterator
&
operator
=
(
const
iterator
&
)
=
default
;
iterator
&
operator
++
()
{
ptr
=
ptr
->
next
;
return
*
this
;
}
iterator
operator
++
(
int
)
{
iterator
res
=
*
this
;
ptr
=
ptr
->
next
;
return
res
;
}
iterator
&
operator
--
()
{
ptr
=
ptr
->
prev
;
return
*
this
;
}
// -- member types -----------------------------------------------------------
iterator
operator
--
(
int
)
{
iterator
res
=
*
this
;
ptr
=
ptr
->
prev
;
return
res
;
}
using
value_type
=
T
;
const
value_type
&
operator
*
()
const
{
return
*
ptr
;
}
using
pointer
=
value_type
*
;
value_type
&
operator
*
()
{
return
*
ptr
;
}
using
node_type
=
typename
value_type
::
node_type
;
pointer
operator
->
()
{
return
ptr
;
}
using
deleter_type
=
Delete
;
bool
operator
==
(
const
iterator
&
other
)
const
{
return
ptr
==
other
.
ptr
;
}
using
iterator
=
bidirectional_iterator
<
T
>
;
bool
operator
!=
(
const
iterator
&
other
)
const
{
return
ptr
!=
other
.
ptr
;
}
using
range
=
std
::
pair
<
iterator
,
iterator
>
;
iterator
next
()
const
{
return
ptr
->
next
;
}
};
// -- constructors, destructors, and assignment operators --------------------
intrusive_
partitioned_list
()
{
partitioned_list
()
{
head_
.
next
=
&
separator_
;
separator_
.
prev
=
&
head_
;
separator_
.
next
=
&
tail_
;
tail_
.
prev
=
&
separator_
;
}
~
intrusive_
partitioned_list
()
{
~
partitioned_list
()
{
clear
();
}
// -- iterators --------------------------------------------------------------
iterator
begin
()
{
return
head_
.
next
;
return
promote
(
head_
.
next
)
;
}
iterator
separator
()
{
...
...
@@ -120,15 +80,13 @@ public:
}
iterator
continuation
()
{
return
separator_
.
next
;
return
promote
(
separator_
.
next
)
;
}
iterator
end
()
{
return
&
tail_
;
}
using
range
=
std
::
pair
<
iterator
,
iterator
>
;
/// Returns the two iterator pairs describing the first and second part
/// of the partitioned list.
std
::
array
<
range
,
2
>
ranges
()
{
...
...
@@ -143,8 +101,8 @@ public:
while
(
i
!=
e
)
{
auto
ptr
=
i
.
ptr
;
++
i
;
f
(
*
p
tr
);
delete_
(
p
tr
);
f
(
*
p
romote
(
ptr
)
);
delete_
(
p
romote
(
ptr
)
);
}
}
if
(
head_
.
next
!=
&
separator_
)
{
...
...
@@ -181,13 +139,13 @@ public:
auto
prev
=
res
->
prev
;
prev
->
next
=
next
;
next
->
prev
=
prev
;
return
res
;
return
promote
(
res
)
;
}
iterator
erase
(
iterator
pos
)
{
auto
next
=
pos
->
next
;
delete_
(
take
(
pos
));
return
next
;
return
promote
(
next
)
;
}
size_t
count
(
size_t
max_count
=
std
::
numeric_limits
<
size_t
>::
max
())
{
...
...
@@ -200,13 +158,13 @@ public:
}
private:
valu
e_type
head_
;
valu
e_type
separator_
;
valu
e_type
tail_
;
nod
e_type
head_
;
nod
e_type
separator_
;
nod
e_type
tail_
;
deleter_type
delete_
;
};
}
// namespace
detail
}
// namespace
intrusive
}
// namespace caf
#endif // CAF_
DETAIL_
INTRUSIVE_PARTITIONED_LIST_HPP
#endif // CAF_INTRUSIVE_PARTITIONED_LIST_HPP
libcaf_core/caf/logger.hpp
View file @
2cbd028b
...
...
@@ -37,6 +37,8 @@
#include "caf/abstract_actor.hpp"
#include "caf/deep_to_string.hpp"
#include "caf/intrusive/doubly_linked.hpp"
#include "caf/detail/scope_guard.hpp"
#include "caf/detail/shared_spinlock.hpp"
#include "caf/detail/pretty_type_name.hpp"
...
...
@@ -65,27 +67,36 @@ public:
friend
class
actor_system
;
/// Encapsulates a single logging event.
struct
event
{
/// Intrusive pointer to the next logging event.
event
*
next
;
/// Intrusive pointer to the previous logging event.
event
*
prev
;
struct
event
:
intrusive
::
doubly_linked
<
event
>
{
event
()
=
default
;
event
(
int
lvl
,
const
char
*
cat
,
const
char
*
fun
,
const
char
*
fn
,
int
line
,
std
::
string
msg
,
std
::
thread
::
id
t
,
actor_id
a
,
timestamp
ts
);
/// Level/priority of the event.
int
level
;
/// Name of the category (component) logging the event.
const
char
*
category_name
;
/// Name of the current context as reported by `__PRETTY_FUNCTION__`.
const
char
*
pretty_fun
;
/// Name of the current file.
const
char
*
file_name
;
/// Current line in the file.
int
line_number
;
/// User-provided message.
std
::
string
message
;
/// Thread ID of the caller.
std
::
thread
::
id
tid
;
/// Actor ID of the caller.
actor_id
aid
;
/// Timestamp of the event.
timestamp
tstamp
;
};
...
...
@@ -343,8 +354,8 @@ inline caf::actor_id caf_set_aid_dummy() { return 0; }
&& CAF_UNIFYN(caf_logger)->accepts(loglvl, component)) \
CAF_UNIFYN(caf_logger) \
->log(new ::caf::logger::event{ \
nullptr, nullptr, loglvl, component, CAF_PRETTY_FUN, __FILE__,
\
__LINE__, (::caf::logger::line_builder{} << message).get(),
\
loglvl, component, CAF_PRETTY_FUN, __FILE__, __LINE__,
\
(::caf::logger::line_builder{} << message).get(),
\
::std::this_thread::get_id(), \
CAF_UNIFYN(caf_logger)->thread_local_aid(), \
::caf::make_timestamp()}); \
...
...
libcaf_core/caf/mailbox_element.hpp
View file @
2cbd028b
...
...
@@ -31,6 +31,8 @@
#include "caf/type_erased_tuple.hpp"
#include "caf/actor_control_block.hpp"
#include "caf/intrusive/doubly_linked.hpp"
#include "caf/meta/type_name.hpp"
#include "caf/meta/omittable_if_empty.hpp"
...
...
@@ -40,16 +42,12 @@
namespace
caf
{
class
mailbox_element
:
public
memory_managed
,
public
message_view
{
class
mailbox_element
:
public
memory_managed
,
public
intrusive
::
doubly_linked
<
mailbox_element
>
,
public
message_view
{
public:
using
forwarding_stack
=
std
::
vector
<
strong_actor_ptr
>
;
/// Intrusive pointer to the next mailbox element.
mailbox_element
*
next
;
/// Intrusive pointer to the previous mailbox element.
mailbox_element
*
prev
;
/// Avoids multi-processing in blocking actors via flagging.
bool
marked
;
...
...
@@ -78,15 +76,15 @@ public:
const
type_erased_tuple
&
content
()
const
;
inline
bool
is_high_priority
()
const
{
return
mid
.
category
()
==
message_id
::
urgent_message_category
;
}
mailbox_element
(
mailbox_element
&&
)
=
delete
;
mailbox_element
(
const
mailbox_element
&
)
=
delete
;
mailbox_element
&
operator
=
(
mailbox_element
&&
)
=
delete
;
mailbox_element
&
operator
=
(
const
mailbox_element
&
)
=
delete
;
inline
bool
is_high_priority
()
const
{
return
mid
.
is_high_priority
();
}
protected:
empty_type_erased_tuple
dummy_
;
};
...
...
libcaf_core/caf/message_id.hpp
View file @
2cbd028b
...
...
@@ -44,7 +44,7 @@ constexpr invalid_message_id_t invalid_message_id = invalid_message_id_t{};
struct
make_message_id_t
;
/// Denotes whether a message is asynchronous or synchronous
/// Denotes whether a message is asynchronous or synchronous
.
/// @note Asynchronous messages always have an invalid message id.
class
message_id
:
detail
::
comparable
<
message_id
>
{
public:
...
...
@@ -54,80 +54,157 @@ public:
// -- constants -------------------------------------------------------------
/// The first bit flags response messages.
static
constexpr
uint64_t
response_flag_mask
=
0x8000000000000000
;
/// The second bit flags whether the actor already responded.
static
constexpr
uint64_t
answered_flag_mask
=
0x4000000000000000
;
static
constexpr
uint64_t
high_prioity_flag_mask
=
0x2000000000000000
;
static
constexpr
uint64_t
request_id_mask
=
0x1FFFFFFFFFFFFFFF
;
// The third and fourth bit are used to categorize messages.
static
constexpr
uint64_t
category_flag_mask
=
0x3000000000000000
;
/// The trailing 60 bits are used for the actual ID.
static
constexpr
uint64_t
request_id_mask
=
0x0FFFFFFFFFFFFFFF
;
/// Identifies one-to-one messages with normal priority.
static
constexpr
uint64_t
default_message_category
=
0
;
// 0b00
/// Identifies stream messages received from upstream actors, e.g.,
/// `stream_msg::batch`.
static
constexpr
uint64_t
upstream_message_category
=
1
;
// 0b01
/// Identifies stream messages received from downstream actors, e.g.,
/// `stream_msg::ack_batch`.
static
constexpr
uint64_t
downstream_message_category
=
2
;
// 0b10
/// Identifies one-to-one messages with high priority.
static
constexpr
uint64_t
urgent_message_category
=
3
;
// 0b11
/// Number of bits trailing the category.
static
constexpr
uint64_t
category_offset
=
60
;
// -- constructors, destructors, and assignment operators -------------------
/// Constructs a message ID for asynchronous messages with normal priority.
constexpr
message_id
()
:
value_
(
0
)
{
// nop
}
constexpr
message_id
(
invalid_message_id_t
)
:
value_
(
0
)
{
/// Constructs a message ID for asynchronous messages with normal priority.
constexpr
message_id
(
invalid_message_id_t
)
:
message_id
()
{
// nop
}
message_id
(
message_id
&&
)
=
default
;
message_id
(
const
message_id
&
)
=
default
;
message_id
&
operator
=
(
message_id
&&
)
=
default
;
message_id
&
operator
=
(
const
message_id
&
)
=
default
;
inline
message_id
&
operator
++
()
{
++
value_
;
return
*
this
;
}
// -- observers -------------------------------------------------------------
/// Returns whether a message is asynchronous, i.e., neither a request nor a
/// stream message.
inline
bool
is_async
()
const
{
return
value_
==
0
||
value_
==
high_prioity_flag_mask
;
return
value_
==
0
||
value_
==
(
urgent_message_category
<<
category_offset
);
}
/// Returns whether a message is a response to a previously send request.
inline
bool
is_response
()
const
{
return
(
value_
&
response_flag_mask
)
!=
0
;
}
/// Returns whether a message is a request.
inline
bool
is_request
()
const
{
return
valid
()
&&
!
is_response
();
}
/// Returns whether a message is tagged as answered by the receiving actor.
inline
bool
is_answered
()
const
{
return
(
value_
&
answered_flag_mask
)
!=
0
;
}
inline
bool
is_high_priority
()
const
{
return
(
value_
&
high_prioity_flag_mask
)
!=
0
;
/// Returns the message category, i.e., one of `default_message_category`,
/// `upstream_message_category`, `downstream_message_category`, or
/// `urgent_message_category`.
inline
uint64_t
category
()
const
{
return
(
value_
&
category_flag_mask
)
>>
category_offset
;
}
inline
bool
valid
()
const
{
return
(
value_
&
request_id_mask
)
!=
0
;
/// Returns whether `category() == default_message_category`.
inline
bool
is_default_message
()
const
{
return
(
value_
&
category_flag_mask
)
==
0
;
}
inline
bool
is_request
()
const
{
return
valid
()
&&
!
is_response
();
/// Returns whether `category() == urgent_message_category`.
inline
bool
is_urgent_message
()
const
{
return
(
value_
&
category_flag_mask
)
==
(
urgent_message_category
<<
category_offset
);
}
/// Returns whether `category() == upstream_message_category`.
inline
bool
is_upstream_message
()
const
{
return
(
value_
&
category_flag_mask
)
==
(
urgent_message_category
<<
category_offset
);
}
/// Returns whether `category() == downstream_message_category`.
inline
bool
is_downstream_message
()
const
{
return
(
value_
&
category_flag_mask
)
==
(
urgent_message_category
<<
category_offset
);
}
/// Returns whether a message is a request or a response.
inline
bool
valid
()
const
{
return
(
value_
&
request_id_mask
)
!=
0
;
}
/// Returns a response ID for the current request or an asynchronous ID with
/// the same priority as this ID.
inline
message_id
response_id
()
const
{
return
message_id
{
is_request
()
?
value_
|
response_flag_mask
:
0
};
if
(
is_request
())
return
message_id
{
value_
|
response_flag_mask
};
return
message_id
{
is_urgent_message
()
?
urgent_message_category
<<
category_offset
:
0u
};
}
/// Extracts the request number part of this ID.
inline
message_id
request_id
()
const
{
return
message_id
(
value_
&
request_id_mask
)
;
return
message_id
{
value_
&
request_id_mask
}
;
}
/// Returns the same ID but with high instead of default message priority.
/// @pre `!is_upstream_message() && !is_downstream_message()`
inline
message_id
with_high_priority
()
const
{
return
message_id
(
value_
|
high_prioity_flag_mask
);
return
message_id
{
value_
|
category_flag_mask
};
// works because urgent == 0b11
}
/// Returns the same ID but with high instead of default message priority.
inline
message_id
with_normal_priority
()
const
{
return
message_id
(
value_
&
~
high_prioity_flag_mask
);
}
inline
void
mark_as_answered
()
{
value_
|=
answered_flag_mask
;
return
message_id
{
value_
&
~
category_flag_mask
};
// works because normal == 0b00
}
/// Returns the "raw bytes" for this ID.
inline
uint64_t
integer_value
()
const
{
return
value_
;
}
long
compare
(
const
message_id
&
other
)
const
{
return
(
value_
==
other
.
value_
)
?
0
:
(
value_
<
other
.
value_
?
-
1
:
1
);
/// Returns a negative value if `*this < other`, zero if `*this == other`,
/// and a positive value otherwise.
inline
int64_t
compare
(
const
message_id
&
other
)
const
{
return
static_cast
<
int64_t
>
(
value_
)
-
static_cast
<
int64_t
>
(
other
.
value_
);
}
// -- mutators --------------------------------------------------------------
inline
message_id
&
operator
++
()
{
++
value_
;
return
*
this
;
}
/// Sets the flag for marking an incoming message as answered.
inline
void
mark_as_answered
()
{
value_
|=
answered_flag_mask
;
}
template
<
class
Inspector
>
...
...
@@ -142,7 +219,7 @@ public:
CAF_DEPRECATED_MSG
(
"use make_message_id instead"
);
private:
constexpr
message_id
(
uint64_t
value
)
:
value_
(
value
)
{
constexpr
explicit
message_id
(
uint64_t
value
)
:
value_
(
value
)
{
// nop
}
...
...
@@ -159,12 +236,11 @@ struct make_message_id_t {
}
constexpr
message_id
operator
()(
uint64_t
value
=
0
)
const
{
return
value
;
return
message_id
{
value
}
;
}
constexpr
message_id
operator
()(
message_priority
p
)
const
{
return
p
==
message_priority
::
high
?
message_id
::
high_prioity_flag_mask
:
0u
;
return
message_id
{
static_cast
<
uint64_t
>
(
p
)
<<
message_id
::
category_offset
};
}
};
...
...
libcaf_core/caf/message_priority.hpp
View file @
2cbd028b
...
...
@@ -25,7 +25,7 @@ namespace caf {
enum
class
message_priority
:
uint32_t
{
normal
,
high
high
=
3
// 0b11, see message_id.hpp why this is important
};
}
// namespace caf
...
...
libcaf_core/caf/scheduled_actor.hpp
View file @
2cbd028b
...
...
@@ -16,8 +16,8 @@
* http://www.boost.org/LICENSE_1_0.txt. *
******************************************************************************/
#ifndef CAF_
ABSTRACT_EVENT_BAS
ED_ACTOR_HPP
#define CAF_
ABSTRACT_EVENT_BAS
ED_ACTOR_HPP
#ifndef CAF_
SCHEDUL
ED_ACTOR_HPP
#define CAF_
SCHEDUL
ED_ACTOR_HPP
#include "caf/config.hpp"
...
...
@@ -881,4 +881,4 @@ protected:
}
// namespace caf
#endif // CAF_
ABSTRACT_EVENT_BAS
ED_ACTOR_HPP
#endif // CAF_
SCHEDUL
ED_ACTOR_HPP
libcaf_core/src/logger.cpp
View file @
2cbd028b
...
...
@@ -112,6 +112,21 @@ inline logger* get_current_logger() {
}
// namespace <anonymous>
logger
::
event
::
event
(
int
lvl
,
const
char
*
cat
,
const
char
*
fun
,
const
char
*
fn
,
int
line
,
std
::
string
msg
,
std
::
thread
::
id
t
,
actor_id
a
,
timestamp
ts
)
:
level
(
lvl
),
category_name
(
cat
),
pretty_fun
(
fun
),
file_name
(
fn
),
line_number
(
line
),
message
(
std
::
move
(
msg
)),
tid
(
std
::
move
(
t
)),
aid
(
a
),
tstamp
(
ts
)
{
// nop
}
logger
::
line_builder
::
line_builder
()
:
behind_arg_
(
false
)
{
// nop
}
...
...
@@ -432,9 +447,7 @@ void logger::log_first_line() {
msg
+=
to_string
(
system_
.
config
().
logger_verbosity
);
msg
+=
", node = "
;
msg
+=
to_string
(
system_
.
node
());
event
tmp
{
nullptr
,
nullptr
,
CAF_LOG_LEVEL_INFO
,
event
tmp
{
CAF_LOG_LEVEL_INFO
,
CAF_LOG_COMPONENT
,
CAF_PRETTY_FUN
,
__FILE__
,
...
...
@@ -447,9 +460,7 @@ void logger::log_first_line() {
}
void
logger
::
log_last_line
()
{
event
tmp
{
nullptr
,
nullptr
,
CAF_LOG_LEVEL_INFO
,
event
tmp
{
CAF_LOG_LEVEL_INFO
,
CAF_LOG_COMPONENT
,
CAF_PRETTY_FUN
,
__FILE__
,
...
...
libcaf_core/src/mailbox_element.cpp
View file @
2cbd028b
...
...
@@ -54,18 +54,13 @@ private:
}
// namespace <anonymous>
mailbox_element
::
mailbox_element
()
:
next
(
nullptr
),
prev
(
nullptr
),
marked
(
false
)
{
mailbox_element
::
mailbox_element
()
:
marked
(
false
)
{
// nop
}
mailbox_element
::
mailbox_element
(
strong_actor_ptr
&&
x
,
message_id
y
,
forwarding_stack
&&
z
)
:
next
(
nullptr
),
prev
(
nullptr
),
marked
(
false
),
:
marked
(
false
),
sender
(
std
::
move
(
x
)),
mid
(
y
),
stages
(
std
::
move
(
z
))
{
...
...
libcaf_core/src/stream_gatherer_impl.cpp
View file @
2cbd028b
...
...
@@ -77,6 +77,7 @@ void stream_gatherer_impl::close(message result) {
for
(
auto
&
path
:
paths_
)
stream_aborter
::
del
(
path
->
hdl
,
self_
->
address
(),
path
->
sid
,
aborter_type
);
paths_
.
clear
();
assignment_vec_
.
clear
();
for
(
auto
&
listener
:
listeners_
)
listener
.
deliver
(
result
);
listeners_
.
clear
();
...
...
@@ -88,6 +89,7 @@ void stream_gatherer_impl::abort(error reason) {
path
->
shutdown_reason
=
reason
;
}
paths_
.
clear
();
assignment_vec_
.
clear
();
for
(
auto
&
listener
:
listeners_
)
listener
.
deliver
(
reason
);
listeners_
.
clear
();
...
...
libcaf_core/test/logger.cpp
View file @
2cbd028b
...
...
@@ -111,8 +111,6 @@ CAF_TEST(rendering) {
CAF_CHECK_EQUAL
(
render
(
logger
::
render_date
,
t0
),
t0_buf
);
// Rendering of events.
logger
::
event
e
{
nullptr
,
nullptr
,
CAF_LOG_LEVEL_WARNING
,
"unit.test"
,
"void ns::foo::bar()"
,
...
...
libcaf_io/caf/io/abstract_broker.hpp
View file @
2cbd028b
...
...
@@ -24,7 +24,8 @@
#include "caf/scheduled_actor.hpp"
#include "caf/prohibit_top_level_spawn_marker.hpp"
#include "caf/detail/intrusive_partitioned_list.hpp"
#include "caf/intrusive/partitioned_list.hpp"
#include "caf/io/fwd.hpp"
#include "caf/io/accept_handle.hpp"
...
...
@@ -425,7 +426,7 @@ private:
scribe_map
scribes_
;
doorman_map
doormen_
;
datagram_servant_map
datagram_servants_
;
detail
::
intrusive_
partitioned_list
<
mailbox_element
,
detail
::
disposer
>
cache_
;
intrusive
::
partitioned_list
<
mailbox_element
,
detail
::
disposer
>
cache_
;
std
::
vector
<
char
>
dummy_wr_buf_
;
};
...
...
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