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
c42dfa97
Commit
c42dfa97
authored
Nov 05, 2012
by
Dominik Charousset
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
maintenance and documentation of group chat
parent
3c15db6a
Changes
4
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
87 additions
and
103 deletions
+87
-103
cppa.files
cppa.files
+0
-1
examples/remote_actors/group_chat.cpp
examples/remote_actors/group_chat.cpp
+53
-60
examples/remote_actors/group_server.cpp
examples/remote_actors/group_server.cpp
+34
-9
examples/remote_actors/type_plugins.hpp
examples/remote_actors/type_plugins.hpp
+0
-33
No files found.
cppa.files
View file @
c42dfa97
...
...
@@ -184,7 +184,6 @@ examples/message_passing/math_actor.cpp
examples/remote_actors/distributed_math_actor.cpp
examples/remote_actors/group_chat.cpp
examples/remote_actors/group_server.cpp
examples/remote_actors/type_plugins.hpp
examples/type_system/announce_1.cpp
examples/type_system/announce_2.cpp
examples/type_system/announce_3.cpp
...
...
examples/remote_actors/group_chat.cpp
View file @
c42dfa97
/******************************************************************************\
* This example program represents a minimal terminal chat program *
* based on group communication. *
* *
* Setup for a minimal chat between "alice" and "bob": *
* - ./build/bin/group_server -p 4242 *
* - ./build/bin/group_chat -g remote:chatroom@localhost:4242 -n alice *
* - ./build/bin/group_chat -g remote:chatroom@localhost:4242 -n bob *
\******************************************************************************/
#include <set>
#include <map>
#include <vector>
...
...
@@ -9,7 +19,6 @@
#include "cppa/opt.hpp"
#include "cppa/cppa.hpp"
#include "type_plugins.hpp"
using
namespace
std
;
using
namespace
cppa
;
...
...
@@ -39,8 +48,7 @@ class client : public event_based_actor {
public:
client
(
const
string
&
name
,
actor_ptr
printer
)
:
m_name
(
name
),
m_printer
(
printer
)
{
}
client
(
string
name
)
:
m_name
(
move
(
name
))
{
}
protected:
...
...
@@ -52,31 +60,34 @@ class client : public event_based_actor {
}
},
on
(
atom
(
"join"
),
arg_match
)
>>
[
=
](
const
group_ptr
&
what
)
{
// accept join commands from local actors only
auto
s
=
self
->
last_sender
();
if
(
s
->
is_proxy
())
{
if
(
self
->
last_sender
()
->
is_proxy
())
{
// accept join commands from local actors only
reply
(
"nice try"
);
}
else
{
for
(
auto
g
:
joined_groups
())
{
cout
<<
"*** leave "
<<
to_string
(
g
)
<<
endl
;
send
(
g
,
m_name
+
" has left the chatroom"
);
leave
(
g
);
}
cout
<<
"*** join "
<<
to_string
(
what
)
<<
endl
;
join
(
what
);
send
(
what
,
m_name
+
" has entered the chatroom"
);
}
},
on
(
atom
(
"quit"
))
>>
[
=
]
{
// ignore quit messages from remote actors
auto
s
=
self
->
last_sender
();
if
(
s
->
is_proxy
())
{
if
(
self
->
last_sender
()
->
is_proxy
())
{
// ignore quit messages from remote actors
reply
(
"nice try"
);
}
else
{
quit
();
}
else
quit
();
},
on
<
string
>
()
>>
[
=
]
{
on
<
string
>
()
>>
[
=
]
(
const
string
&
txt
)
{
// don't print own messages
if
(
last_sender
()
!=
this
)
forward_to
(
m_printer
)
;
if
(
last_sender
()
!=
this
)
cout
<<
txt
<<
endl
;
},
others
()
>>
[
=
]()
{
send
(
m_printer
,
to_string
(
last_dequeued
()))
;
cout
<<
"unexpected: "
<<
to_string
(
last_dequeued
())
<<
endl
;
}
);
}
...
...
@@ -84,91 +95,74 @@ class client : public event_based_actor {
private:
string
m_name
;
actor_ptr
m_printer
;
};
class
print_actor
:
public
event_based_actor
{
void
init
()
{
become
(
on
(
atom
(
"quit"
))
>>
[]
{
self
->
quit
();
},
on_arg_match
>>
[](
const
string
&
str
)
{
cout
<<
str
<<
endl
;
}
);
}
};
auto
main
(
int
argc
,
char
*
argv
[])
->
int
{
// enables this client to print user-defined types
// without changing this source code
exec_plugin
();
int
main
(
int
argc
,
char
**
argv
)
{
string
name
;
vector
<
string
>
group_ids
;
string
group_id
;
options_description
desc
;
bool
args_valid
=
argc
>
1
&&
match_stream
<
string
>
(
argv
+
1
,
argv
+
argc
)
(
bool
args_valid
=
match_stream
<
string
>
(
argv
+
1
,
argv
+
argc
)
(
on_opt
(
'n'
,
"name"
,
&
desc
,
"set name"
)
>>
rd_arg
(
name
),
on_opt
(
'g'
,
"group"
,
&
desc
,
"join group <arg
>"
)
>>
add_arg
(
group_ids
),
on_opt
(
'g'
,
"group"
,
&
desc
,
"join group <arg
1>"
)
>>
rd_arg
(
group_id
),
on_vopt
(
'h'
,
"help"
,
&
desc
,
"print help"
)
>>
print_desc_and_exit
(
&
desc
)
);
if
(
!
args_valid
)
print_desc_and_exit
(
&
desc
)();
auto
printer
=
spawn
<
print_actor
>
();
if
(
!
args_valid
)
print_desc_and_exit
(
&
desc
)();
while
(
name
.
empty
())
{
send
(
printer
,
"*** what is your name for chatting?"
);
if
(
!
getline
(
cin
,
name
))
return
1
;
cout
<<
"please enter your name: "
<<
flush
;
if
(
!
getline
(
cin
,
name
))
{
cerr
<<
"*** no name given... terminating"
<<
endl
;
return
1
;
}
}
send
(
printer
,
"*** starting client."
)
;
auto
client_actor
=
spawn
<
client
>
(
name
,
printer
);
cout
<<
"*** starting client, type '/help' for a list of commands"
<<
endl
;
auto
client_actor
=
spawn
<
client
>
(
name
);
// evaluate group parameters
for
(
auto
&
gid
:
group_ids
)
{
auto
p
=
gid
.
find
(
':'
);
if
(
!
group_id
.
empty
()
)
{
auto
p
=
g
roup_
id
.
find
(
':'
);
if
(
p
==
std
::
string
::
npos
)
{
cerr
<<
"*** error parsing argument "
<<
gid
cerr
<<
"*** error parsing argument "
<<
g
roup_
id
<<
", expected format: <module_name>:<group_id>"
;
}
else
{
try
{
auto
g
=
group
::
get
(
gid
.
substr
(
0
,
p
),
gid
.
substr
(
p
+
1
));
auto
g
=
group
::
get
(
g
roup_
id
.
substr
(
0
,
p
),
g
roup_
id
.
substr
(
p
+
1
));
send
(
client_actor
,
atom
(
"join"
),
g
);
}
catch
(
exception
&
e
)
{
ostringstream
err
;
err
<<
"*** exception: group::get(
\"
"
<<
gid
.
substr
(
0
,
p
)
<<
"
\"
,
\"
"
<<
gid
.
substr
(
p
+
1
)
<<
"
\"
) failed; "
<<
to_verbose_string
(
e
)
<<
endl
;
send
(
printer
,
err
.
str
());
cerr
<<
"*** exception: group::get(
\"
"
<<
group_id
.
substr
(
0
,
p
)
<<
"
\"
,
\"
"
<<
group_id
.
substr
(
p
+
1
)
<<
"
\"
) failed; "
<<
to_verbose_string
(
e
)
<<
endl
;
}
}
}
istream_iterator
<
line
>
lines
(
cin
);
istream_iterator
<
line
>
eof
;
match_each
(
lines
,
eof
,
split_line
)
(
match_each
(
lines
,
eof
,
split_line
)
(
on
(
"/join"
,
arg_match
)
>>
[
&
](
const
string
&
mod
,
const
string
&
id
)
{
try
{
send
(
client_actor
,
atom
(
"join"
),
group
::
get
(
mod
,
id
));
}
catch
(
exception
&
e
)
{
send
(
printer
,
string
(
"*** exception: "
)
+
e
.
what
())
;
cerr
<<
"*** exception: "
<<
to_verbose_string
(
e
)
<<
endl
;
}
},
on
(
"/quit"
)
>>
[
&
]
{
close
(
0
);
// close STDIN
close
(
STDIN_FILENO
);
// close STDIN; causes this match loop to quit
},
on
<
string
,
anything
>
().
when
(
_x1
.
starts_with
(
"/"
))
>>
[
&
]
{
send
(
printer
,
"*** available commands:
\n
"
"/join MODULE GROUP
\n
"
"/quit"
);
cout
<<
"*** available commands:
\n
"
" /join <module> <group> join a new chat channel
\n
"
" /quit quit the program
\n
"
" /help print this text
\n
"
<<
flush
;
},
others
()
>>
[
&
]
{
if
(
s_last_line
.
size
()
>
0
)
{
...
...
@@ -182,7 +176,6 @@ auto main(int argc, char* argv[]) -> int {
}
);
send
(
client_actor
,
atom
(
"quit"
));
send
(
printer
,
atom
(
"quit"
));
await_all_others_done
();
shutdown
();
return
0
;
...
...
examples/remote_actors/group_server.cpp
View file @
c42dfa97
/******************************************************************************\
* This example program represents a minimal IRC-like group *
* communication server. *
* *
* Setup for a minimal chat between "alice" and "bob": *
* - ./build/bin/group_server -p 4242 *
* - ./build/bin/group_chat -g remote:chatroom@localhost:4242 -n alice *
* - ./build/bin/group_chat -g remote:chatroom@localhost:4242 -n bob *
\******************************************************************************/
#include <string>
#include <dlfcn.h>
#include <sstream>
#include <iostream>
#include "cppa/opt.hpp"
#include "cppa/cppa.hpp"
#include "type_plugins.hpp"
using
namespace
std
;
using
namespace
cppa
;
int
main
(
int
argc
,
char
**
argv
)
{
// enables this server to be used with user-defined types
// without changing this source code
exec_plugin
();
uint16_t
port
=
0
;
options_description
desc
;
bool
args_valid
=
argc
>
1
&&
match_stream
<
string
>
(
argv
+
1
,
argv
+
argc
)
(
...
...
@@ -21,11 +25,32 @@ int main(int argc, char** argv) {
on_vopt
(
'h'
,
"help"
,
&
desc
,
"print help"
)
>>
print_desc_and_exit
(
&
desc
)
);
if
(
port
<=
1024
)
{
cout
<<
"no port > 1024 given"
<<
endl
;
cerr
<<
"*** no port > 1024 given"
<<
endl
;
args_valid
=
false
;
}
if
(
!
args_valid
)
{
// print_desc(&desc) returns a function printing the stored help text
print_desc
(
&
desc
)();
return
1
;
}
try
{
// try to bind the group server to the given port,
// this allows other nodes to access groups of this server via
// group::get("remote", "<group>@<host>:<port>");
// note: it is not needed to explicitly create a <group> on the server,
// as groups are created on-the-fly on first usage
publish_local_groups_at
(
port
);
}
catch
(
bind_failure
&
e
)
{
// thrown if <port> is already in use
cerr
<<
"*** bind_failure: "
<<
e
.
what
()
<<
endl
;
return
2
;
}
catch
(
network_error
&
e
)
{
// thrown on errors in the socket API
cerr
<<
"*** network error: "
<<
e
.
what
()
<<
endl
;
return
2
;
}
if
(
!
args_valid
)
return
1
;
publish_local_groups_at
(
port
);
cout
<<
"type 'quit' to shutdown the server"
<<
endl
;
string
line
;
while
(
getline
(
cin
,
line
))
{
...
...
examples/remote_actors/type_plugins.hpp
deleted
100644 → 0
View file @
3c15db6a
#ifndef TYPE_PLUGINS_HPP
#define TYPE_PLUGINS_HPP
#include <dlfcn.h>
#include <iostream>
#include "cppa/cppa.hpp"
inline
void
exec_plugin
()
{
using
namespace
std
;
using
namespace
cppa
;
// user-defined types can be announced by a plugin
void
*
handle
=
dlopen
(
"plugin.dylib"
,
RTLD_NOW
);
// macos
if
(
!
handle
)
handle
=
dlopen
(
"plugin.so"
,
RTLD_NOW
);
// linux
if
(
handle
)
{
auto
before
=
uniform_type_info
::
instances
();
cout
<<
"found a plugin, call exec_plugin()"
<<
endl
;
auto
fun
=
(
void
(
*
)())
dlsym
(
handle
,
"exec_plugin"
);
if
(
fun
)
{
fun
();
cout
<<
"the plugin announced the following types:"
<<
endl
;
for
(
auto
inf
:
uniform_type_info
::
instances
())
{
if
(
count
(
begin
(
before
),
end
(
before
),
inf
)
==
0
)
{
cout
<<
inf
->
name
()
<<
endl
;
}
}
}
else
{
cerr
<<
"*** plugin did not define symbol exec_plugin!"
<<
endl
;
}
}
}
#endif // TYPE_PLUGINS_HPP
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