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
a19cb8e6
Unverified
Commit
a19cb8e6
authored
Jul 27, 2023
by
Samir Halilčević
Committed by
GitHub
Jul 27, 2023
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Refactor multiplexer to be an interface
parent
bb22e7fe
Changes
6
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
554 additions
and
659 deletions
+554
-659
libcaf_net/CMakeLists.txt
libcaf_net/CMakeLists.txt
+0
-1
libcaf_net/caf/detail/pollset_updater.cpp
libcaf_net/caf/detail/pollset_updater.cpp
+0
-102
libcaf_net/caf/detail/pollset_updater.hpp
libcaf_net/caf/detail/pollset_updater.hpp
+0
-64
libcaf_net/caf/net/fwd.hpp
libcaf_net/caf/net/fwd.hpp
+0
-6
libcaf_net/caf/net/multiplexer.cpp
libcaf_net/caf/net/multiplexer.cpp
+531
-334
libcaf_net/caf/net/multiplexer.hpp
libcaf_net/caf/net/multiplexer.hpp
+23
-152
No files found.
libcaf_net/CMakeLists.txt
View file @
a19cb8e6
...
...
@@ -29,7 +29,6 @@ caf_add_component(
${
CAF_NET_HEADERS
}
SOURCES
caf/detail/convert_ip_endpoint.cpp
caf/detail/pollset_updater.cpp
caf/detail/rfc6455.cpp
caf/detail/rfc6455.test.cpp
caf/net/abstract_actor_shell.cpp
...
...
libcaf_net/caf/detail/pollset_updater.cpp
deleted
100644 → 0
View file @
bb22e7fe
// This file is part of CAF, the C++ Actor Framework. See the file LICENSE in
// the main distribution directory for license terms and copyright or visit
// https://github.com/actor-framework/actor-framework/blob/master/LICENSE.
#include "caf/detail/pollset_updater.hpp"
#include "caf/net/multiplexer.hpp"
#include "caf/action.hpp"
#include "caf/actor_system.hpp"
#include "caf/logger.hpp"
#include "caf/sec.hpp"
#include "caf/span.hpp"
#include <cstring>
namespace
caf
::
detail
{
// -- constructors, destructors, and assignment operators ----------------------
pollset_updater
::
pollset_updater
(
net
::
pipe_socket
fd
)
:
fd_
(
fd
)
{
// nop
}
// -- factories ----------------------------------------------------------------
std
::
unique_ptr
<
pollset_updater
>
pollset_updater
::
make
(
net
::
pipe_socket
fd
)
{
return
std
::
make_unique
<
pollset_updater
>
(
fd
);
}
// -- interface functions ------------------------------------------------------
error
pollset_updater
::
start
(
net
::
socket_manager
*
owner
)
{
CAF_LOG_TRACE
(
""
);
owner_
=
owner
;
mpx_
=
owner
->
mpx_ptr
();
return
net
::
nonblocking
(
fd_
,
true
);
}
net
::
socket
pollset_updater
::
handle
()
const
{
return
fd_
;
}
void
pollset_updater
::
handle_read_event
()
{
CAF_LOG_TRACE
(
""
);
auto
as_mgr
=
[](
intptr_t
ptr
)
{
return
intrusive_ptr
{
reinterpret_cast
<
net
::
socket_manager
*>
(
ptr
),
false
};
};
auto
add_action
=
[
this
](
intptr_t
ptr
)
{
auto
f
=
action
{
intrusive_ptr
{
reinterpret_cast
<
action
::
impl
*>
(
ptr
),
false
}};
mpx_
->
pending_actions_
.
push_back
(
std
::
move
(
f
));
};
for
(;;)
{
CAF_ASSERT
((
buf_
.
size
()
-
buf_size_
)
>
0
);
auto
num_bytes
=
read
(
fd_
,
make_span
(
buf_
.
data
()
+
buf_size_
,
buf_
.
size
()
-
buf_size_
));
if
(
num_bytes
>
0
)
{
buf_size_
+=
static_cast
<
size_t
>
(
num_bytes
);
if
(
buf_
.
size
()
==
buf_size_
)
{
buf_size_
=
0
;
auto
opcode
=
static_cast
<
uint8_t
>
(
buf_
[
0
]);
intptr_t
ptr
;
memcpy
(
&
ptr
,
buf_
.
data
()
+
1
,
sizeof
(
intptr_t
));
switch
(
static_cast
<
code
>
(
opcode
))
{
case
code
:
:
start_manager
:
mpx_
->
do_start
(
as_mgr
(
ptr
));
break
;
case
code
:
:
run_action
:
add_action
(
ptr
);
break
;
case
code
:
:
shutdown
:
CAF_ASSERT
(
ptr
==
0
);
mpx_
->
do_shutdown
();
break
;
default:
CAF_LOG_ERROR
(
"opcode not recognized: "
<<
CAF_ARG
(
opcode
));
break
;
}
}
}
else
if
(
num_bytes
==
0
)
{
CAF_LOG_DEBUG
(
"pipe closed, assume shutdown"
);
owner_
->
deregister
();
return
;
}
else
if
(
net
::
last_socket_error_is_temporary
())
{
return
;
}
else
{
CAF_LOG_ERROR
(
"pollset updater failed to read from the pipe"
);
owner_
->
deregister
();
return
;
}
}
}
void
pollset_updater
::
handle_write_event
()
{
owner_
->
deregister_writing
();
}
void
pollset_updater
::
abort
(
const
error
&
)
{
// nop
}
}
// namespace caf::detail
libcaf_net/caf/detail/pollset_updater.hpp
deleted
100644 → 0
View file @
bb22e7fe
// This file is part of CAF, the C++ Actor Framework. See the file LICENSE in
// the main distribution directory for license terms and copyright or visit
// https://github.com/actor-framework/actor-framework/blob/master/LICENSE.
#pragma once
#include "caf/net/pipe_socket.hpp"
#include "caf/net/socket_event_layer.hpp"
#include "caf/net/socket_manager.hpp"
#include "caf/detail/net_export.hpp"
#include <array>
#include <cstddef>
#include <cstdint>
#include <mutex>
namespace
caf
::
detail
{
class
CAF_NET_EXPORT
pollset_updater
:
public
net
::
socket_event_layer
{
public:
// -- member types -----------------------------------------------------------
using
super
=
net
::
socket_manager
;
using
msg_buf
=
std
::
array
<
std
::
byte
,
sizeof
(
intptr_t
)
+
1
>
;
enum
class
code
:
uint8_t
{
start_manager
,
shutdown_reading
,
shutdown_writing
,
run_action
,
shutdown
,
};
// -- constructors, destructors, and assignment operators --------------------
explicit
pollset_updater
(
net
::
pipe_socket
fd
);
// -- factories --------------------------------------------------------------
static
std
::
unique_ptr
<
pollset_updater
>
make
(
net
::
pipe_socket
fd
);
// -- implementation of socket_event_layer -----------------------------------
error
start
(
net
::
socket_manager
*
owner
)
override
;
net
::
socket
handle
()
const
override
;
void
handle_read_event
()
override
;
void
handle_write_event
()
override
;
void
abort
(
const
error
&
reason
)
override
;
private:
net
::
pipe_socket
fd_
;
net
::
socket_manager
*
owner_
=
nullptr
;
net
::
multiplexer
*
mpx_
=
nullptr
;
msg_buf
buf_
;
size_t
buf_size_
=
0
;
};
}
// namespace caf::detail
libcaf_net/caf/net/fwd.hpp
View file @
a19cb8e6
...
...
@@ -90,12 +90,6 @@ enum class errc;
}
// namespace caf::net::octet_stream
namespace
caf
::
detail
{
class
pollset_updater
;
}
// namespace caf::detail
namespace
caf
::
net
::
lp
{
class
client
;
...
...
libcaf_net/caf/net/multiplexer.cpp
View file @
a19cb8e6
This diff is collapsed.
Click to expand it.
libcaf_net/caf/net/multiplexer.hpp
View file @
a19cb8e6
...
...
@@ -5,54 +5,25 @@
#pragma once
#include "caf/net/fwd.hpp"
#include "caf/net/pipe_socket.hpp"
#include "caf/net/socket.hpp"
#include "caf/action.hpp"
#include "caf/async/execution_context.hpp"
#include "caf/detail/atomic_ref_counted.hpp"
#include "caf/detail/net_export.hpp"
#include "caf/ref_counted.hpp"
#include "caf/unordered_flat_map.hpp"
#include <deque>
#include <memory>
#include <mutex>
#include <thread>
extern
"C"
{
struct
pollfd
;
}
// extern "C"
namespace
caf
::
net
{
/// Multiplexes any number of ::socket_manager objects with a ::socket.
class
CAF_NET_EXPORT
multiplexer
:
public
detail
::
atomic_ref_counted
,
public
async
::
execution_context
{
class
CAF_NET_EXPORT
multiplexer
:
public
async
::
execution_context
{
public:
// -- member types -----------------------------------------------------------
struct
poll_update
{
short
events
=
0
;
socket_manager_ptr
mgr
;
};
using
poll_update_map
=
unordered_flat_map
<
socket
,
poll_update
>
;
using
pollfd_list
=
std
::
vector
<
pollfd
>
;
using
manager_list
=
std
::
vector
<
socket_manager_ptr
>
;
// -- friends ----------------------------------------------------------------
friend
class
detail
::
pollset_updater
;
// Needs access to the `do_*` functions.
// -- static utility functions -----------------------------------------------
/// Blocks the PIPE signal on the current thread when running on
a POSIX
///
windows. Has no effect when running on Windows
.
/// Blocks the PIPE signal on the current thread when running on
Linux. Has no
///
effect otherwise
.
static
void
block_sigpipe
();
/// Returns a pointer to the multiplexer from the actor system.
...
...
@@ -60,179 +31,79 @@ public:
// -- constructors, destructors, and assignment operators --------------------
~
multiplexer
();
~
multiplexer
()
override
;
// -- factories --------------------------------------------------------------
/// Creates a new multiplexer instance with the default implementation.
/// @param parent Points to the owning middleman instance. May be `nullptr`
/// only for the purpose of unit testing if no @ref
/// socket_manager requires access to the @ref middleman or the
/// @ref actor_system.
static
multiplexer_ptr
make
(
middleman
*
parent
)
{
auto
ptr
=
new
multiplexer
(
parent
);
return
multiplexer_ptr
{
ptr
,
false
};
}
static
multiplexer_ptr
make
(
middleman
*
parent
);
// -- initialization ---------------------------------------------------------
error
init
()
;
virtual
error
init
()
=
0
;
// -- properties -------------------------------------------------------------
/// Returns the number of currently active socket managers.
size_t
num_socket_managers
()
const
noexcept
;
/// Returns the index of `mgr` in the pollset or `-1`.
ptrdiff_t
index_of
(
const
socket_manager_ptr
&
mgr
)
const
noexcept
;
/// Returns the index of `fd` in the pollset or `-1`.
ptrdiff_t
index_of
(
socket
fd
)
const
noexcept
;
virtual
size_t
num_socket_managers
()
const
noexcept
=
0
;
/// Returns the owning @ref middleman instance.
middleman
&
owner
()
;
virtual
middleman
&
owner
()
=
0
;
/// Returns the enclosing @ref actor_system.
actor_system
&
system
();
// -- implementation of execution_context ------------------------------------
void
ref_execution_context
()
const
noexcept
override
;
void
deref_execution_context
()
const
noexcept
override
;
void
schedule
(
action
what
)
override
;
void
watch
(
disposable
what
)
override
;
virtual
actor_system
&
system
()
=
0
;
// -- thread-safe signaling --------------------------------------------------
/// Registers `mgr` for initialization in the multiplexer's thread.
/// @thread-safe
v
oid
start
(
socket_manager_ptr
mgr
)
;
v
irtual
void
start
(
socket_manager_ptr
mgr
)
=
0
;
/// Signals the multiplexer to initiate shutdown.
/// @thread-safe
v
oid
shutdown
()
;
v
irtual
void
shutdown
()
=
0
;
// -- callbacks for socket managers ------------------------------------------
/// Registers `mgr` for read events.
v
oid
register_reading
(
socket_manager
*
mgr
)
;
v
irtual
void
register_reading
(
socket_manager
*
mgr
)
=
0
;
/// Registers `mgr` for write events.
v
oid
register_writing
(
socket_manager
*
mgr
)
;
v
irtual
void
register_writing
(
socket_manager
*
mgr
)
=
0
;
/// Deregisters `mgr` from read events.
v
oid
deregister_reading
(
socket_manager
*
mgr
)
;
v
irtual
void
deregister_reading
(
socket_manager
*
mgr
)
=
0
;
/// Deregisters `mgr` from write events.
v
oid
deregister_writing
(
socket_manager
*
mgr
)
;
v
irtual
void
deregister_writing
(
socket_manager
*
mgr
)
=
0
;
/// Deregisters @p mgr from read and write events.
v
oid
deregister
(
socket_manager
*
mgr
)
;
v
irtual
void
deregister
(
socket_manager
*
mgr
)
=
0
;
/// Queries whether `mgr` is currently registered for reading.
bool
is_reading
(
const
socket_manager
*
mgr
)
const
noexcept
;
virtual
bool
is_reading
(
const
socket_manager
*
mgr
)
const
noexcept
=
0
;
/// Queries whether `mgr` is currently registered for writing.
bool
is_writing
(
const
socket_manager
*
mgr
)
const
noexcept
;
virtual
bool
is_writing
(
const
socket_manager
*
mgr
)
const
noexcept
=
0
;
// -- control flow -----------------------------------------------------------
/// Polls I/O activity once and runs all socket event handlers that become
/// ready as a result.
bool
poll_once
(
bool
blocking
);
/// Runs `poll_once(false)` until it returns `true`.`
void
poll
();
virtual
bool
poll_once
(
bool
blocking
)
=
0
;
/// Applies all pending updates.
void
apply_updates
();
/// Runs all pending actions.
void
run_actions
();
virtual
void
apply_updates
()
=
0
;
/// Sets the thread ID to `std::this_thread::id()`.
v
oid
set_thread_id
()
;
v
irtual
void
set_thread_id
()
=
0
;
/// Runs the multiplexer until no socket event handler remains active.
void
run
();
protected:
// -- utility functions ------------------------------------------------------
/// Handles an I/O event on given manager.
void
handle
(
const
socket_manager_ptr
&
mgr
,
short
events
,
short
revents
);
/// Returns a change entry for the socket at given index. Lazily creates a new
/// entry before returning if necessary.
poll_update
&
update_for
(
ptrdiff_t
index
);
/// Returns a change entry for the socket of the manager.
poll_update
&
update_for
(
socket_manager
*
mgr
);
/// Writes `opcode` and pointer to `mgr` the the pipe for handling an event
/// later via the pollset updater.
/// @warning assumes ownership of @p ptr.
template
<
class
T
>
void
write_to_pipe
(
uint8_t
opcode
,
T
*
ptr
);
/// @copydoc write_to_pipe
template
<
class
Enum
,
class
T
>
std
::
enable_if_t
<
std
::
is_enum_v
<
Enum
>>
write_to_pipe
(
Enum
opcode
,
T
*
ptr
)
{
write_to_pipe
(
static_cast
<
uint8_t
>
(
opcode
),
ptr
);
}
/// Queries the currently active event bitmask for `mgr`.
short
active_mask_of
(
const
socket_manager
*
mgr
)
const
noexcept
;
// -- member variables -------------------------------------------------------
/// Bookkeeping data for managed sockets.
pollfd_list
pollset_
;
/// Maps sockets to their owning managers by storing the managers in the same
/// order as their sockets appear in `pollset_`.
manager_list
managers_
;
/// Caches changes to the events mask of managed sockets until they can safely
/// take place.
poll_update_map
updates_
;
/// Stores the ID of the thread this multiplexer is running in. Set when
/// calling `init()`.
std
::
thread
::
id
tid_
;
/// Guards `write_handle_`.
std
::
mutex
write_lock_
;
/// Used for pushing updates to the multiplexer's thread.
pipe_socket
write_handle_
;
/// Points to the owning middleman.
middleman
*
owner_
;
/// Signals whether shutdown has been requested.
bool
shutting_down_
=
false
;
/// Pending actions via `schedule`.
std
::
deque
<
action
>
pending_actions_
;
/// Keeps track of watched disposables.
std
::
vector
<
disposable
>
watched_
;
private:
// -- constructors, destructors, and assignment operators --------------------
explicit
multiplexer
(
middleman
*
parent
);
// -- internal callbacks the pollset updater ---------------------------------
void
do_shutdown
();
void
do_register_reading
(
const
socket_manager_ptr
&
mgr
);
void
do_start
(
const
socket_manager_ptr
&
mgr
);
virtual
void
run
()
=
0
;
};
}
// namespace caf::net
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