Commit 193319d7 authored by Dominik Charousset's avatar Dominik Charousset

Merge pull request #328 from actor-framework/topic/visual_studio

Fix build on MSVC
parents 196ae5f6 36077a3c
...@@ -196,6 +196,9 @@ if(MINGW) ...@@ -196,6 +196,9 @@ if(MINGW)
else() else()
set(EXTRA_FLAGS "${EXTRA_FLAGS} -fPIC") set(EXTRA_FLAGS "${EXTRA_FLAGS} -fPIC")
endif() endif()
if (WIN32)
set(LD_FLAGS ${LD_FLAGS} ws2_32 iphlpapi)
endif()
# iOS support # iOS support
if(CAF_OSX_SYSROOT) if(CAF_OSX_SYSROOT)
set(CMAKE_OSX_SYSROOT "${CAF_OSX_SYSROOT}") set(CMAKE_OSX_SYSROOT "${CAF_OSX_SYSROOT}")
......
...@@ -7,6 +7,8 @@ ...@@ -7,6 +7,8 @@
* - ./build/bin/broker -c localhost 4242 * * - ./build/bin/broker -c localhost 4242 *
\ ******************************************************************************/ \ ******************************************************************************/
#include "caf/config.hpp"
#ifdef WIN32 #ifdef WIN32
# define _WIN32_WINNT 0x0600 # define _WIN32_WINNT 0x0600
# include <Winsock2.h> # include <Winsock2.h>
......
...@@ -129,13 +129,15 @@ private: ...@@ -129,13 +129,15 @@ private:
using std::swap; using std::swap;
swap(host_, nhost); swap(host_, nhost);
swap(port_, nport); swap(port_, nport);
auto send_mm = [=] {
unbecome();
send(mm, get_atom::value, host_, port_);
};
// await pending ok/error message first, then send new request to MM // await pending ok/error message first, then send new request to MM
become( become(
keep_behavior, keep_behavior,
(on<ok_atom, actor_addr>() || on<error_atom, string>()) >> [=] { [=](ok_atom&, actor_addr&) { send_mm(); },
unbecome(); [=](error_atom&, string&) { send_mm(); }
send(mm, get_atom::value, host_, port_);
}
); );
}, },
// simply ignore all requests until we have a connection // simply ignore all requests until we have a connection
...@@ -171,10 +173,10 @@ optional<int> toint(const string& str) { ...@@ -171,10 +173,10 @@ optional<int> toint(const string& str) {
// converts "+" to the atom '+' and "-" to the atom '-' // converts "+" to the atom '+' and "-" to the atom '-'
optional<atom_value> plus_or_minus(const string& str) { optional<atom_value> plus_or_minus(const string& str) {
if (str == "+") { if (str == "+") {
return {plus_atom::value}; return optional<atom_value>{plus_atom::value};
} }
if (str == "-") { if (str == "-") {
return {minus_atom::value}; return optional<atom_value>{minus_atom::value};
} }
return none; return none;
} }
...@@ -195,15 +197,18 @@ void client_repl(string host, uint16_t port) { ...@@ -195,15 +197,18 @@ void client_repl(string host, uint16_t port) {
// defining the handler outside the loop is more efficient as it avoids // defining the handler outside the loop is more efficient as it avoids
// re-creating the same object over and over again // re-creating the same object over and over again
message_handler eval{ message_handler eval{
on("quit") >> [&] { [&](const string& cmd) {
if (cmd != "quit")
return;
anon_send_exit(client, exit_reason::user_shutdown); anon_send_exit(client, exit_reason::user_shutdown);
done = true; done = true;
}, },
on("connect", arg_match) >> [&](string& nhost, string& sport) { [&](string& arg0, string& arg1, string& arg2) {
if (arg0 == "connect") {
try { try {
auto lport = std::stoul(sport); auto lport = std::stoul(arg2);
if (lport < std::numeric_limits<uint16_t>::max()) { if (lport < std::numeric_limits<uint16_t>::max()) {
anon_send(client, rebind_atom::value, move(nhost), anon_send(client, rebind_atom::value, move(arg1),
static_cast<uint16_t>(lport)); static_cast<uint16_t>(lport));
} }
else { else {
...@@ -211,12 +216,17 @@ void client_repl(string host, uint16_t port) { ...@@ -211,12 +216,17 @@ void client_repl(string host, uint16_t port) {
} }
} }
catch (std::exception&) { catch (std::exception&) {
cout << "\"" << sport << "\" is not an unsigned integer" cout << "\"" << arg2 << "\" is not an unsigned integer"
<< endl; << endl;
} }
}, }
on(toint, plus_or_minus, toint) >> [&](int x, atom_value op, int y) { else {
anon_send(client, op, x, y); auto x = toint(arg0);
auto op = plus_or_minus(arg1);
auto y = toint(arg2);
if (x && y && op)
anon_send(client, *op, *x, *y);
}
}, },
others >> usage others >> usage
}; };
......
...@@ -113,21 +113,19 @@ int main(int argc, char** argv) { ...@@ -113,21 +113,19 @@ int main(int argc, char** argv) {
} }
} }
cout << "*** starting client, type '/help' for a list of commands" << endl; cout << "*** starting client, type '/help' for a list of commands" << endl;
auto starts_with = [](const string& str) -> function<optional<string> (const string&)> {
return [=](const string& arg) -> optional<string> {
if (arg.compare(0, str.size(), str) == 0) {
return arg;
}
return none;
};
};
istream_iterator<line> eof; istream_iterator<line> eof;
vector<string> words; vector<string> words;
for (istream_iterator<line> i(cin); i != eof; ++i) { for (istream_iterator<line> i(cin); i != eof; ++i) {
auto send_input = [&] {
if (!i->str.empty()) {
anon_send(client_actor, broadcast_atom::value, i->str);
}
};
words.clear(); words.clear();
split(words, i->str, is_any_of(" ")); split(words, i->str, is_any_of(" "));
message_builder(words.begin(), words.end()).apply({ message_builder(words.begin(), words.end()).apply({
on("/join", arg_match) >> [&](const string& mod, const string& id) { [&](const string& cmd, const string& mod, const string& id) {
if (cmd == "/join") {
try { try {
group grp = (mod == "remote") ? io::remote_group(id) group grp = (mod == "remote") ? io::remote_group(id)
: group::get(mod, id); : group::get(mod, id);
...@@ -136,22 +134,26 @@ int main(int argc, char** argv) { ...@@ -136,22 +134,26 @@ int main(int argc, char** argv) {
catch (exception& e) { catch (exception& e) {
cerr << "*** exception: " << to_verbose_string(e) << endl; cerr << "*** exception: " << to_verbose_string(e) << endl;
} }
}
else {
send_input();
}
}, },
on("/quit") >> [&] { [&](const string& cmd) {
// close STDIN; causes this match loop to quit if (cmd == "/quit") {
cin.setstate(ios_base::eofbit); cin.setstate(ios_base::eofbit);
}, }
on(starts_with("/"), any_vals) >> [&] { else if (cmd[0] == '/') {
cout << "*** available commands:\n" cout << "*** available commands:\n"
" /join <module> <group> join a new chat channel\n" " /join <module> <group> join a new chat channel\n"
" /quit quit the program\n" " /quit quit the program\n"
" /help print this text\n" << flush; " /help print this text\n" << flush;
},
others >> [&] {
if (! i->str.empty()) {
anon_send(client_actor, broadcast_atom::value, i->str);
} }
else {
send_input();
} }
},
others >> send_input
}); });
} }
// force actor to quit // force actor to quit
......
...@@ -50,14 +50,14 @@ void testee(event_based_actor* self, size_t remaining) { ...@@ -50,14 +50,14 @@ void testee(event_based_actor* self, size_t remaining) {
self->become ( self->become (
// note: we sent a foo_pair2, but match on foo_pair // note: we sent a foo_pair2, but match on foo_pair
// that's safe because both are aliases for std::pair<int, int> // that's safe because both are aliases for std::pair<int, int>
on<foo_pair>() >> [=](const foo_pair& val) { [=](const foo_pair& val) {
cout << "foo_pair(" cout << "foo_pair("
<< val.first << ", " << val.first << ", "
<< val.second << ")" << val.second << ")"
<< endl; << endl;
set_next_behavior(); set_next_behavior();
}, },
on<foo>() >> [=](const foo& val) { [=](const foo& val) {
cout << "foo({"; cout << "foo({";
auto i = val.a.begin(); auto i = val.a.begin();
auto end = val.a.end(); auto end = val.a.end();
......
...@@ -41,7 +41,7 @@ bool operator==(const foo& lhs, const foo& rhs) { ...@@ -41,7 +41,7 @@ bool operator==(const foo& lhs, const foo& rhs) {
void testee(event_based_actor* self) { void testee(event_based_actor* self) {
self->become ( self->become (
on<foo>() >> [=](const foo& val) { [=](const foo& val) {
aout(self) << "foo(" aout(self) << "foo("
<< val.a() << ", " << val.a() << ", "
<< val.b() << ")" << val.b() << ")"
......
...@@ -48,7 +48,7 @@ using foo_setter = void (foo::*)(int); ...@@ -48,7 +48,7 @@ using foo_setter = void (foo::*)(int);
void testee(event_based_actor* self) { void testee(event_based_actor* self) {
self->become ( self->become (
on<foo>() >> [=](const foo& val) { [=](const foo& val) {
aout(self) << "foo(" aout(self) << "foo("
<< val.a() << ", " << val.a() << ", "
<< val.b() << ")" << val.b() << ")"
......
...@@ -85,7 +85,7 @@ void testee(event_based_actor* self, size_t remaining) { ...@@ -85,7 +85,7 @@ void testee(event_based_actor* self, size_t remaining) {
else self->quit(); else self->quit();
}; };
self->become ( self->become (
on<bar>() >> [=](const bar& val) { [=](const bar& val) {
aout(self) << "bar(foo(" aout(self) << "bar(foo("
<< val.f.a() << ", " << val.f.a() << ", "
<< val.f.b() << "), " << val.f.b() << "), "
...@@ -93,7 +93,7 @@ void testee(event_based_actor* self, size_t remaining) { ...@@ -93,7 +93,7 @@ void testee(event_based_actor* self, size_t remaining) {
<< endl; << endl;
set_next_behavior(); set_next_behavior();
}, },
on<baz>() >> [=](const baz& val) { [=](const baz& val) {
// prints: baz ( foo ( 1, 2 ), bar ( foo ( 3, 4 ), 5 ) ) // prints: baz ( foo ( 1, 2 ), bar ( foo ( 3, 4 ), 5 ) )
aout(self) << to_string(make_message(val)) << endl; aout(self) << to_string(make_message(val)) << endl;
set_next_behavior(); set_next_behavior();
......
...@@ -20,6 +20,8 @@ ...@@ -20,6 +20,8 @@
#ifndef CAF_DETAIL_SINGLE_READER_QUEUE_HPP #ifndef CAF_DETAIL_SINGLE_READER_QUEUE_HPP
#define CAF_DETAIL_SINGLE_READER_QUEUE_HPP #define CAF_DETAIL_SINGLE_READER_QUEUE_HPP
#include "caf/config.hpp"
#include <list> #include <list>
#include <deque> #include <deque>
#include <mutex> #include <mutex>
...@@ -28,8 +30,6 @@ ...@@ -28,8 +30,6 @@
#include <limits> #include <limits>
#include <condition_variable> // std::cv_status #include <condition_variable> // std::cv_status
#include "caf/config.hpp"
#include "caf/detail/intrusive_partitioned_list.hpp" #include "caf/detail/intrusive_partitioned_list.hpp"
namespace caf { namespace caf {
......
...@@ -20,6 +20,8 @@ ...@@ -20,6 +20,8 @@
#ifndef CAF_SCHEDULER_COORDINATOR_HPP #ifndef CAF_SCHEDULER_COORDINATOR_HPP
#define CAF_SCHEDULER_COORDINATOR_HPP #define CAF_SCHEDULER_COORDINATOR_HPP
#include "caf/config.hpp"
#include <thread> #include <thread>
#include <limits> #include <limits>
#include <memory> #include <memory>
......
...@@ -20,6 +20,8 @@ ...@@ -20,6 +20,8 @@
#ifndef CAF_SET_SCHEDULER_HPP #ifndef CAF_SET_SCHEDULER_HPP
#define CAF_SET_SCHEDULER_HPP #define CAF_SET_SCHEDULER_HPP
#include "caf/config.hpp"
#include <thread> #include <thread>
#include <limits> #include <limits>
......
...@@ -39,16 +39,17 @@ namespace detail { ...@@ -39,16 +39,17 @@ namespace detail {
namespace { namespace {
pthread_key_t s_key; using cache_map = std::map<const std::type_info*, std::unique_ptr<memory_cache>>;
pthread_once_t s_key_once = PTHREAD_ONCE_INIT;
} // namespace <anonymous> } // namespace <anonymous>
memory_cache::~memory_cache() { #ifdef CAF_CLANG
// nop namespace {
}
pthread_key_t s_key;
pthread_once_t s_key_once = PTHREAD_ONCE_INIT;
using cache_map = std::map<const std::type_info*,std::unique_ptr<memory_cache>>; } // namespace <anonymous>
void cache_map_destructor(void* ptr) { void cache_map_destructor(void* ptr) {
delete reinterpret_cast<cache_map*>(ptr); delete reinterpret_cast<cache_map*>(ptr);
...@@ -71,6 +72,30 @@ cache_map& get_cache_map() { ...@@ -71,6 +72,30 @@ cache_map& get_cache_map() {
return *cache; return *cache;
} }
#else // !CAF_CLANG
namespace {
thread_local std::unique_ptr<cache_map> s_key;
}
cache_map& get_cache_map() {
if (! s_key) {
s_key = std::unique_ptr<cache_map>(new cache_map);
// insert default types
std::unique_ptr<memory_cache> tmp(new basic_memory_cache<mailbox_element>);
s_key->emplace(&typeid(mailbox_element), move(tmp));
}
return *s_key;
}
#endif
memory_cache::~memory_cache() {
// nop
}
memory_cache* memory::get_cache_map_entry(const std::type_info* tinf) { memory_cache* memory::get_cache_map_entry(const std::type_info* tinf) {
auto& cache = get_cache_map(); auto& cache = get_cache_map();
auto i = cache.find(tinf); auto i = cache.find(tinf);
......
...@@ -235,7 +235,7 @@ uint16_t port_of_fd(native_socket fd); ...@@ -235,7 +235,7 @@ uint16_t port_of_fd(native_socket fd);
ccall(cc_zero, "listen() failed", listen, listener, 1); ccall(cc_zero, "listen() failed", listen, listener, 1);
// create read-only end of the pipe // create read-only end of the pipe
DWORD flags = 0; DWORD flags = 0;
auto read_fd = ccall(cc_valid_socket, "WSASocket() failed", WSASocket, auto read_fd = ccall(cc_valid_socket, "WSASocketW() failed", WSASocketW,
AF_INET, SOCK_STREAM, 0, nullptr, 0, flags); AF_INET, SOCK_STREAM, 0, nullptr, 0, flags);
ccall(cc_zero, "connect() failed", connect, read_fd, ccall(cc_zero, "connect() failed", connect, read_fd,
&a.addr, int{sizeof(a.inaddr)}); &a.addr, int{sizeof(a.inaddr)});
...@@ -915,10 +915,10 @@ bool write_some(size_t& result, native_socket fd, const void* buf, size_t len) { ...@@ -915,10 +915,10 @@ bool write_some(size_t& result, native_socket fd, const void* buf, size_t len) {
bool try_accept(native_socket& result, native_socket fd) { bool try_accept(native_socket& result, native_socket fd) {
CAF_LOGF_TRACE(CAF_ARG(fd)); CAF_LOGF_TRACE(CAF_ARG(fd));
sockaddr addr; sockaddr_storage addr;
memset(&addr, 0, sizeof(addr)); memset(&addr, 0, sizeof(addr));
socklen_t addrlen = sizeof(addr); socklen_t addrlen = sizeof(addr);
result = ::accept(fd, &addr, &addrlen); result = ::accept(fd, reinterpret_cast<sockaddr*>(&addr), &addrlen);
CAF_LOGF_DEBUG("tried to accept a new connection from from socket " CAF_LOGF_DEBUG("tried to accept a new connection from from socket "
<< fd << ", accept returned " << result); << fd << ", accept returned " << result);
if (result == invalid_native_socket) { if (result == invalid_native_socket) {
......
...@@ -33,8 +33,6 @@ ...@@ -33,8 +33,6 @@
# include <winsock2.h> # include <winsock2.h>
# include <ws2tcpip.h> # include <ws2tcpip.h>
# include <iphlpapi.h> # include <iphlpapi.h>
# pragma comment(lib, "ws2_32.lib")
# pragma comment(lib, "iphlpapi.lib")
#else #else
# include <sys/socket.h> # include <sys/socket.h>
# include <netinet/in.h> # include <netinet/in.h>
...@@ -134,7 +132,7 @@ void for_each_device(bool include_localhost, F fun) { ...@@ -134,7 +132,7 @@ void for_each_device(bool include_localhost, F fun) {
nullptr, retval, nullptr, retval,
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
(LPTSTR) &msgbuf, 0, nullptr)) { (LPTSTR) &msgbuf, 0, nullptr)) {
printf("Error: %s", msgbuf); printf("Error: %s", static_cast<char*>(msgbuf));
LocalFree(msgbuf); LocalFree(msgbuf);
} }
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment