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
783cd02d
Commit
783cd02d
authored
Apr 25, 2012
by
neverlord
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
select()
parent
69ef1b78
Changes
10
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
10 changed files
with
288 additions
and
523 deletions
+288
-523
Makefile.am
Makefile.am
+2
-2
cppa.files
cppa.files
+0
-2
cppa/detail/network_manager.hpp
cppa/detail/network_manager.hpp
+3
-2
cppa/detail/post_office.hpp
cppa/detail/post_office.hpp
+9
-1
cppa/detail/post_office_msg.hpp
cppa/detail/post_office_msg.hpp
+0
-155
src/actor_proxy_cache.cpp
src/actor_proxy_cache.cpp
+2
-5
src/network_manager.cpp
src/network_manager.cpp
+18
-2
src/post_office.cpp
src/post_office.cpp
+235
-246
src/post_office_msg.cpp
src/post_office_msg.cpp
+0
-100
src/unicast_network.cpp
src/unicast_network.cpp
+19
-8
No files found.
Makefile.am
View file @
783cd02d
...
@@ -39,7 +39,6 @@ libcppa_la_SOURCES = \
...
@@ -39,7 +39,6 @@ libcppa_la_SOURCES = \
src/partial_function.cpp
\
src/partial_function.cpp
\
src/pattern.cpp
\
src/pattern.cpp
\
src/post_office.cpp
\
src/post_office.cpp
\
src/post_office_msg.cpp
\
src/primitive_variant.cpp
\
src/primitive_variant.cpp
\
src/process_information.cpp
\
src/process_information.cpp
\
src/receive.cpp
\
src/receive.cpp
\
...
@@ -102,6 +101,7 @@ nobase_library_include_HEADERS = \
...
@@ -102,6 +101,7 @@ nobase_library_include_HEADERS = \
cppa/detail/demangle.hpp
\
cppa/detail/demangle.hpp
\
cppa/detail/disablable_delete.hpp
\
cppa/detail/disablable_delete.hpp
\
cppa/detail/empty_tuple.hpp
\
cppa/detail/empty_tuple.hpp
\
cppa/detail/filter_result.hpp
\
cppa/detail/get_behavior.hpp
\
cppa/detail/get_behavior.hpp
\
cppa/detail/group_manager.hpp
\
cppa/detail/group_manager.hpp
\
cppa/detail/implicit_conversions.hpp
\
cppa/detail/implicit_conversions.hpp
\
...
@@ -112,12 +112,12 @@ nobase_library_include_HEADERS = \
...
@@ -112,12 +112,12 @@ nobase_library_include_HEADERS = \
cppa/detail/matches.hpp
\
cppa/detail/matches.hpp
\
cppa/detail/mock_scheduler.hpp
\
cppa/detail/mock_scheduler.hpp
\
cppa/detail/native_socket.hpp
\
cppa/detail/native_socket.hpp
\
cppa/detail/nestable_receive_actor.hpp
\
cppa/detail/network_manager.hpp
\
cppa/detail/network_manager.hpp
\
cppa/detail/object_array.hpp
\
cppa/detail/object_array.hpp
\
cppa/detail/object_impl.hpp
\
cppa/detail/object_impl.hpp
\
cppa/detail/pair_member.hpp
\
cppa/detail/pair_member.hpp
\
cppa/detail/post_office.hpp
\
cppa/detail/post_office.hpp
\
cppa/detail/post_office_msg.hpp
\
cppa/detail/primitive_member.hpp
\
cppa/detail/primitive_member.hpp
\
cppa/detail/projection.hpp
\
cppa/detail/projection.hpp
\
cppa/detail/pseudo_tuple.hpp
\
cppa/detail/pseudo_tuple.hpp
\
...
...
cppa.files
View file @
783cd02d
...
@@ -169,8 +169,6 @@ src/actor_registry.cpp
...
@@ -169,8 +169,6 @@ src/actor_registry.cpp
cppa/detail/uniform_type_info_map.hpp
cppa/detail/uniform_type_info_map.hpp
cppa/detail/network_manager.hpp
cppa/detail/network_manager.hpp
src/network_manager.cpp
src/network_manager.cpp
cppa/detail/post_office_msg.hpp
src/post_office_msg.cpp
cppa/detail/group_manager.hpp
cppa/detail/group_manager.hpp
src/group_manager.cpp
src/group_manager.cpp
cppa/detail/empty_tuple.hpp
cppa/detail/empty_tuple.hpp
...
...
cppa/detail/network_manager.hpp
View file @
783cd02d
...
@@ -31,8 +31,7 @@
...
@@ -31,8 +31,7 @@
#ifndef NETWORK_MANAGER_HPP
#ifndef NETWORK_MANAGER_HPP
#define NETWORK_MANAGER_HPP
#define NETWORK_MANAGER_HPP
#include "cppa/detail/mailman.hpp"
#include "cppa/detail/post_office.hpp"
#include "cppa/detail/post_office_msg.hpp"
namespace
cppa
{
namespace
detail
{
namespace
cppa
{
namespace
detail
{
...
@@ -47,6 +46,8 @@ class network_manager
...
@@ -47,6 +46,8 @@ class network_manager
virtual
void
stop
()
=
0
;
virtual
void
stop
()
=
0
;
virtual
void
send_to_post_office
(
po_message
const
&
msg
)
=
0
;
virtual
void
send_to_post_office
(
any_tuple
msg
)
=
0
;
virtual
void
send_to_post_office
(
any_tuple
msg
)
=
0
;
virtual
void
send_to_mailman
(
any_tuple
msg
)
=
0
;
virtual
void
send_to_mailman
(
any_tuple
msg
)
=
0
;
...
...
cppa/detail/post_office.hpp
View file @
783cd02d
...
@@ -33,12 +33,20 @@
...
@@ -33,12 +33,20 @@
#include <memory>
#include <memory>
#include "cppa/atom.hpp"
#include "cppa/actor_proxy.hpp"
#include "cppa/actor_proxy.hpp"
#include "cppa/detail/native_socket.hpp"
#include "cppa/detail/native_socket.hpp"
namespace
cppa
{
namespace
detail
{
namespace
cppa
{
namespace
detail
{
void
post_office_loop
();
struct
po_message
{
atom_value
flag
;
native_socket_type
fd
;
actor_id
aid
;
};
void
post_office_loop
(
int
input_fd
);
void
post_office_add_peer
(
native_socket_type
peer_socket
,
void
post_office_add_peer
(
native_socket_type
peer_socket
,
process_information_ptr
const
&
peer_ptr
);
process_information_ptr
const
&
peer_ptr
);
...
...
cppa/detail/post_office_msg.hpp
deleted
100644 → 0
View file @
69ef1b78
/******************************************************************************\
* ___ __ *
* /\_ \ __/\ \ *
* \//\ \ /\_\ \ \____ ___ _____ _____ __ *
* \ \ \ \/\ \ \ '__`\ /'___\/\ '__`\/\ '__`\ /'__`\ *
* \_\ \_\ \ \ \ \L\ \/\ \__/\ \ \L\ \ \ \L\ \/\ \L\.\_ *
* /\____\\ \_\ \_,__/\ \____\\ \ ,__/\ \ ,__/\ \__/.\_\ *
* \/____/ \/_/\/___/ \/____/ \ \ \/ \ \ \/ \/__/\/_/ *
* \ \_\ \ \_\ *
* \/_/ \/_/ *
* *
* Copyright (C) 2011, 2012 *
* Dominik Charousset <dominik.charousset@haw-hamburg.de> *
* *
* This file is part of libcppa. *
* libcppa is free software: you can redistribute it and/or modify it under *
* the terms of the GNU Lesser General Public License as published by the *
* Free Software Foundation, either version 3 of the License *
* or (at your option) any later version. *
* *
* libcppa is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. *
* See the GNU Lesser General Public License for more details. *
* *
* You should have received a copy of the GNU Lesser General Public License *
* along with libcppa. If not, see <http://www.gnu.org/licenses/>. *
\******************************************************************************/
#ifndef POST_OFFICE_MSG_HPP
#define POST_OFFICE_MSG_HPP
#include "cppa/attachable.hpp"
#include "cppa/actor_proxy.hpp"
#include "cppa/intrusive_ptr.hpp"
#include "cppa/process_information.hpp"
#include "cppa/detail/native_socket.hpp"
#include "cppa/intrusive/single_reader_queue.hpp"
namespace
cppa
{
namespace
detail
{
class
post_office_msg
{
public:
enum
msg_type
{
invalid_type
,
add_peer_type
,
add_server_socket_type
,
proxy_exited_type
};
struct
add_peer
{
native_socket_type
sockfd
;
process_information_ptr
peer
;
actor_proxy_ptr
first_peer_actor
;
std
::
unique_ptr
<
attachable
>
attachable_ptr
;
add_peer
(
native_socket_type
peer_socket
,
process_information_ptr
const
&
peer_ptr
,
actor_proxy_ptr
const
&
peer_actor_ptr
,
std
::
unique_ptr
<
attachable
>&&
peer_observer
);
};
struct
add_server_socket
{
native_socket_type
server_sockfd
;
actor_ptr
published_actor
;
add_server_socket
(
native_socket_type
ssockfd
,
actor_ptr
const
&
whom
);
};
struct
proxy_exited
{
actor_proxy_ptr
proxy_ptr
;
inline
proxy_exited
(
actor_proxy_ptr
const
&
who
)
:
proxy_ptr
(
who
)
{
}
};
inline
post_office_msg
()
:
next
(
nullptr
),
m_type
(
invalid_type
)
{
}
post_office_msg
(
native_socket_type
arg0
,
process_information_ptr
const
&
arg1
,
actor_proxy_ptr
const
&
arg2
,
std
::
unique_ptr
<
attachable
>&&
arg3
);
post_office_msg
(
native_socket_type
arg0
,
actor_ptr
const
&
arg1
);
post_office_msg
(
actor_proxy_ptr
const
&
proxy_ptr
);
inline
bool
is_add_peer_msg
()
const
{
return
m_type
==
add_peer_type
;
}
inline
bool
is_add_server_socket_msg
()
const
{
return
m_type
==
add_server_socket_type
;
}
inline
bool
is_proxy_exited_msg
()
const
{
return
m_type
==
proxy_exited_type
;
}
inline
add_peer
&
as_add_peer_msg
()
{
return
m_add_peer_msg
;
}
inline
add_server_socket
&
as_add_server_socket_msg
()
{
return
m_add_server_socket
;
}
inline
proxy_exited
&
as_proxy_exited_msg
()
{
return
m_proxy_exited
;
}
~
post_office_msg
();
post_office_msg
*
next
;
private:
msg_type
m_type
;
union
{
add_peer
m_add_peer_msg
;
add_server_socket
m_add_server_socket
;
proxy_exited
m_proxy_exited
;
};
};
constexpr
std
::
uint32_t
rd_queue_event
=
0x00
;
constexpr
std
::
uint32_t
unpublish_actor_event
=
0x01
;
constexpr
std
::
uint32_t
close_socket_event
=
0x02
;
constexpr
std
::
uint32_t
shutdown_event
=
0x03
;
typedef
std
::
uint32_t
pipe_msg
[
2
];
constexpr
size_t
pipe_msg_size
=
2
*
sizeof
(
std
::
uint32_t
);
}
}
// namespace cppa::detail
#endif // POST_OFFICE_MSG_HPP
src/actor_proxy_cache.cpp
View file @
783cd02d
...
@@ -86,14 +86,11 @@ actor_proxy_ptr actor_proxy_cache::get(key_tuple const& key)
...
@@ -86,14 +86,11 @@ actor_proxy_ptr actor_proxy_cache::get(key_tuple const& key)
}
}
m_entries
.
insert
(
std
::
make_pair
(
key
,
result
));
m_entries
.
insert
(
std
::
make_pair
(
key
,
result
));
}
}
auto
msg
=
make_any_tuple
(
atom
(
"ADD_PROXY"
),
result
);
singleton_manager
::
get_network_manager
()
->
send_to_post_office
(
std
::
move
(
msg
));
result
->
enqueue
(
nullptr
,
make_any_tuple
(
atom
(
"MONITOR"
)));
result
->
attach_functor
([
result
](
std
::
uint32_t
)
result
->
attach_functor
([
result
](
std
::
uint32_t
)
{
{
auto
msg
=
make_any_tuple
(
atom
(
"RM_PROXY"
),
result
);
get_actor_proxy_cache
().
erase
(
result
);
singleton_manager
::
get_network_manager
()
->
send_to_post_office
(
std
::
move
(
msg
));
});
});
result
->
enqueue
(
nullptr
,
make_any_tuple
(
atom
(
"MONITOR"
)));
return
result
;
return
result
;
}
}
...
...
src/network_manager.cpp
View file @
783cd02d
...
@@ -41,7 +41,6 @@
...
@@ -41,7 +41,6 @@
#include "cppa/detail/mailman.hpp"
#include "cppa/detail/mailman.hpp"
#include "cppa/detail/post_office.hpp"
#include "cppa/detail/post_office.hpp"
#include "cppa/detail/mock_scheduler.hpp"
#include "cppa/detail/mock_scheduler.hpp"
#include "cppa/detail/post_office_msg.hpp"
#include "cppa/detail/network_manager.hpp"
#include "cppa/detail/network_manager.hpp"
#include "cppa/detail/converted_thread_context.hpp"
#include "cppa/detail/converted_thread_context.hpp"
...
@@ -59,10 +58,17 @@ struct network_manager_impl : network_manager
...
@@ -59,10 +58,17 @@ struct network_manager_impl : network_manager
local_actor_ptr
m_post_office
;
local_actor_ptr
m_post_office
;
thread
m_post_office_thread
;
thread
m_post_office_thread
;
int
pipe_fd
[
2
];
void
start
()
// override
void
start
()
// override
{
{
if
(
pipe
(
pipe_fd
)
!=
0
)
{
CPPA_CRITICAL
(
"cannot create pipe"
);
}
m_post_office
.
reset
(
new
converted_thread_context
);
m_post_office
.
reset
(
new
converted_thread_context
);
m_post_office_thread
=
mock_scheduler
::
spawn_hidden_impl
(
post_office_loop
,
m_post_office
);
m_post_office_thread
=
mock_scheduler
::
spawn_hidden_impl
(
std
::
bind
(
post_office_loop
,
pipe_fd
[
0
])
,
m_post_office
);
m_mailman
.
reset
(
new
converted_thread_context
);
m_mailman
.
reset
(
new
converted_thread_context
);
m_mailman_thread
=
mock_scheduler
::
spawn_hidden_impl
(
mailman_loop
,
m_mailman
);
m_mailman_thread
=
mock_scheduler
::
spawn_hidden_impl
(
mailman_loop
,
m_mailman
);
...
@@ -74,6 +80,16 @@ struct network_manager_impl : network_manager
...
@@ -74,6 +80,16 @@ struct network_manager_impl : network_manager
m_mailman
->
enqueue
(
nullptr
,
make_any_tuple
(
atom
(
"DONE"
)));
m_mailman
->
enqueue
(
nullptr
,
make_any_tuple
(
atom
(
"DONE"
)));
m_post_office_thread
.
join
();
m_post_office_thread
.
join
();
m_mailman_thread
.
join
();
m_mailman_thread
.
join
();
close
(
pipe_fd
[
0
]);
close
(
pipe_fd
[
0
]);
}
void
send_to_post_office
(
po_message
const
&
msg
)
{
if
(
write
(
pipe_fd
[
1
],
&
msg
,
sizeof
(
po_message
))
!=
sizeof
(
po_message
))
{
CPPA_CRITICAL
(
"cannot write to pipe"
);
}
}
}
void
send_to_post_office
(
any_tuple
msg
)
void
send_to_post_office
(
any_tuple
msg
)
...
...
src/post_office.cpp
View file @
783cd02d
This diff is collapsed.
Click to expand it.
src/post_office_msg.cpp
deleted
100644 → 0
View file @
69ef1b78
/******************************************************************************\
* ___ __ *
* /\_ \ __/\ \ *
* \//\ \ /\_\ \ \____ ___ _____ _____ __ *
* \ \ \ \/\ \ \ '__`\ /'___\/\ '__`\/\ '__`\ /'__`\ *
* \_\ \_\ \ \ \ \L\ \/\ \__/\ \ \L\ \ \ \L\ \/\ \L\.\_ *
* /\____\\ \_\ \_,__/\ \____\\ \ ,__/\ \ ,__/\ \__/.\_\ *
* \/____/ \/_/\/___/ \/____/ \ \ \/ \ \ \/ \/__/\/_/ *
* \ \_\ \ \_\ *
* \/_/ \/_/ *
* *
* Copyright (C) 2011, 2012 *
* Dominik Charousset <dominik.charousset@haw-hamburg.de> *
* *
* This file is part of libcppa. *
* libcppa is free software: you can redistribute it and/or modify it under *
* the terms of the GNU Lesser General Public License as published by the *
* Free Software Foundation, either version 3 of the License *
* or (at your option) any later version. *
* *
* libcppa is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. *
* See the GNU Lesser General Public License for more details. *
* *
* You should have received a copy of the GNU Lesser General Public License *
* along with libcppa. If not, see <http://www.gnu.org/licenses/>. *
\******************************************************************************/
#include "cppa/detail/post_office_msg.hpp"
namespace
cppa
{
namespace
detail
{
post_office_msg
::
add_peer
::
add_peer
(
native_socket_type
peer_socket
,
const
process_information_ptr
&
peer_ptr
,
const
actor_proxy_ptr
&
peer_actor_ptr
,
std
::
unique_ptr
<
attachable
>&&
peer_observer
)
:
sockfd
(
peer_socket
)
,
peer
(
peer_ptr
)
,
first_peer_actor
(
peer_actor_ptr
)
,
attachable_ptr
(
std
::
move
(
peer_observer
))
{
}
post_office_msg
::
add_server_socket
::
add_server_socket
(
native_socket_type
ssockfd
,
const
actor_ptr
&
whom
)
:
server_sockfd
(
ssockfd
)
,
published_actor
(
whom
)
{
}
post_office_msg
::
post_office_msg
(
native_socket_type
arg0
,
const
process_information_ptr
&
arg1
,
const
actor_proxy_ptr
&
arg2
,
std
::
unique_ptr
<
attachable
>&&
arg3
)
:
next
(
nullptr
)
,
m_type
(
add_peer_type
)
{
new
(
&
m_add_peer_msg
)
add_peer
(
arg0
,
arg1
,
arg2
,
std
::
move
(
arg3
));
}
post_office_msg
::
post_office_msg
(
native_socket_type
arg0
,
const
actor_ptr
&
arg1
)
:
next
(
nullptr
)
,
m_type
(
add_server_socket_type
)
{
new
(
&
m_add_server_socket
)
add_server_socket
(
arg0
,
arg1
);
}
post_office_msg
::
post_office_msg
(
const
actor_proxy_ptr
&
proxy_ptr
)
:
next
(
nullptr
)
,
m_type
(
proxy_exited_type
)
{
new
(
&
m_proxy_exited
)
proxy_exited
(
proxy_ptr
);
}
post_office_msg
::~
post_office_msg
()
{
switch
(
m_type
)
{
case
add_peer_type
:
{
m_add_peer_msg
.
~
add_peer
();
break
;
}
case
add_server_socket_type
:
{
m_add_server_socket
.
~
add_server_socket
();
break
;
}
case
proxy_exited_type
:
{
m_proxy_exited
.
~
proxy_exited
();
break
;
}
default:
break
;
}
}
}
}
// namespace cppa::detail
src/unicast_network.cpp
View file @
783cd02d
...
@@ -129,6 +129,14 @@ void publish(actor_ptr& whom, std::uint16_t port)
...
@@ -129,6 +129,14 @@ void publish(actor_ptr& whom, std::uint16_t port)
serv_addr
.
sin_family
=
AF_INET
;
serv_addr
.
sin_family
=
AF_INET
;
serv_addr
.
sin_addr
.
s_addr
=
INADDR_ANY
;
serv_addr
.
sin_addr
.
s_addr
=
INADDR_ANY
;
serv_addr
.
sin_port
=
htons
(
port
);
serv_addr
.
sin_port
=
htons
(
port
);
if
(
bind
(
sockfd
,
(
struct
sockaddr
*
)
&
serv_addr
,
sizeof
(
serv_addr
))
<
0
)
{
throw
bind_failure
(
errno
);
}
if
(
listen
(
sockfd
,
10
)
!=
0
)
{
throw
network_error
(
"listen() failed"
);
}
int
flags
=
fcntl
(
sockfd
,
F_GETFL
,
0
);
int
flags
=
fcntl
(
sockfd
,
F_GETFL
,
0
);
if
(
flags
==
-
1
)
if
(
flags
==
-
1
)
{
{
...
@@ -140,14 +148,6 @@ void publish(actor_ptr& whom, std::uint16_t port)
...
@@ -140,14 +148,6 @@ void publish(actor_ptr& whom, std::uint16_t port)
}
}
flags
=
1
;
flags
=
1
;
setsockopt
(
sockfd
,
IPPROTO_TCP
,
TCP_NODELAY
,
&
flags
,
sizeof
(
int
));
setsockopt
(
sockfd
,
IPPROTO_TCP
,
TCP_NODELAY
,
&
flags
,
sizeof
(
int
));
if
(
bind
(
sockfd
,
(
struct
sockaddr
*
)
&
serv_addr
,
sizeof
(
serv_addr
))
<
0
)
{
throw
bind_failure
(
errno
);
}
if
(
listen
(
sockfd
,
10
)
!=
0
)
{
throw
network_error
(
"listen() failed"
);
}
// ok, no exceptions
// ok, no exceptions
sguard
.
release
();
sguard
.
release
();
detail
::
post_office_publish
(
sockfd
,
whom
);
detail
::
post_office_publish
(
sockfd
,
whom
);
...
@@ -195,6 +195,17 @@ actor_ptr remote_actor(const char* host, std::uint16_t port)
...
@@ -195,6 +195,17 @@ actor_ptr remote_actor(const char* host, std::uint16_t port)
read_from_socket
(
sockfd
,
&
remote_actor_id
,
sizeof
(
remote_actor_id
));
read_from_socket
(
sockfd
,
&
remote_actor_id
,
sizeof
(
remote_actor_id
));
read_from_socket
(
sockfd
,
&
peer_pid
,
sizeof
(
std
::
uint32_t
));
read_from_socket
(
sockfd
,
&
peer_pid
,
sizeof
(
std
::
uint32_t
));
read_from_socket
(
sockfd
,
peer_node_id
.
data
(),
peer_node_id
.
size
());
read_from_socket
(
sockfd
,
peer_node_id
.
data
(),
peer_node_id
.
size
());
flags
=
fcntl
(
sockfd
,
F_GETFL
,
0
);
if
(
flags
==
-
1
)
{
throw
network_error
(
"unable to get socket flags"
);
}
if
(
fcntl
(
sockfd
,
F_SETFL
,
flags
|
O_NONBLOCK
)
<
0
)
{
throw
network_error
(
"unable to set socket to nonblock"
);
}
auto
peer_pinf
=
new
process_information
(
peer_pid
,
peer_node_id
);
auto
peer_pinf
=
new
process_information
(
peer_pid
,
peer_node_id
);
process_information_ptr
pinfptr
(
peer_pinf
);
process_information_ptr
pinfptr
(
peer_pinf
);
auto
key
=
std
::
make_tuple
(
remote_actor_id
,
pinfptr
->
process_id
(),
pinfptr
->
node_id
());
auto
key
=
std
::
make_tuple
(
remote_actor_id
,
pinfptr
->
process_id
(),
pinfptr
->
node_id
());
...
...
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