Skip to content

Commit 438e119

Browse files
Jaulertgockel
authored andcommitted
Adds boost::future as an implementation of zk::future
This changes `zk::future`, `zk::promise`, `zk::async`, and `zk::launch` to use the Standard Library or Boost based on the `ZKPP_FUTURE` build setting set to "Boost". This also changes exceptions to support Boost's boost::current_exception by throwing all exceptions through `zk::throw_exception`, which aliases `boost::throw_exception`.
1 parent 8d9fdef commit 438e119

13 files changed

+203
-79
lines changed

CMakeLists.txt

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@ configuration_setting(NAME FUTURE
7070
OPTIONS
7171
STD
7272
STD_EXPERIMENTAL
73+
BOOST
7374
CUSTOM
7475
)
7576

@@ -89,9 +90,20 @@ set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -O3")
8990
################################################################################
9091

9192
find_library(zookeeper_LIBRARIES zookeeper_mt)
93+
set(ZKPP_LIB_DEPENDENCIES ${ZKPP_LIB_DEPENDENCIES} ${zookeeper_LIBRARIES})
9294

9395
include_directories("${PROJECT_SOURCE_DIR}/src")
9496

97+
if (ZKPP_BUILD_SETTING_FUTURE STREQUAL "BOOST")
98+
find_package(Boost
99+
1.52.0
100+
REQUIRED
101+
thread)
102+
set(ZKPP_LIB_DEPENDENCIES ${ZKPP_LIB_DEPENDENCIES} ${Boost_LIBRARIES})
103+
endif()
104+
105+
106+
95107
################################################################################
96108
# GTest #
97109
################################################################################
@@ -147,8 +159,8 @@ build_module(NAME zkpp
147159
PATH src/zk
148160
NO_RECURSE
149161
LINK_LIBRARIES
150-
${zookeeper_LIBRARIES}
151-
)
162+
${ZKPP_LIB_DEPENDENCIES}
163+
)
152164

153165
build_module(NAME zkpp-server
154166
PATH src/zk/server

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ Ultimately, the usage looks like this (assuming you have a ZooKeeper server runn
4444

4545
/** All result types are printable for debugging purposes. **/
4646
template <typename T>
47-
void print_thing(const std::future<T>& result)
47+
void print_thing(const zk::future<T>& result)
4848
{
4949
try
5050
{

src/zk/client.cpp

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
#include "acl.hpp"
33
#include "connection.hpp"
44
#include "multi.hpp"
5+
#include "exceptions.hpp"
56

67
#include <sstream>
78
#include <ostream>
@@ -45,24 +46,24 @@ future<client> client::connect(connection_params conn_params)
4546
else
4647
{
4748
// TODO: Test if future::then can be relied on and use that instead of std::async
48-
return std::async
49+
return zk::async
4950
(
50-
std::launch::async,
51+
zk::launch::async,
5152
[state_change_fut = std::move(state_change_fut), conn = std::move(conn)] () mutable -> client
5253
{
5354
state s(state_change_fut.get());
5455
if (s == state::connected)
5556
return client(conn);
5657
else
57-
throw std::runtime_error(std::string("Unexpected state: ") + to_string(s));
58+
zk::throw_exception(std::runtime_error(std::string("Unexpected state: ") + to_string(s)));
5859
}
5960
);
6061
}
6162
}
6263
catch (...)
6364
{
6465
promise<client> p;
65-
p.set_exception(std::current_exception());
66+
p.set_exception(zk::current_exception());
6667
return p.get_future();
6768
}
6869
}

src/zk/connection.cpp

Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
#include "connection_zk.hpp"
33
#include "error.hpp"
44
#include "types.hpp"
5+
#include "exceptions.hpp"
56

67
#include <algorithm>
78
#include <regex>
@@ -47,7 +48,7 @@ void connection::on_session_event(zk::state new_state)
4748

4849
auto ex = new_state == zk::state::expired_session ? get_exception_ptr_of(error_code::session_expired)
4950
: new_state == zk::state::authentication_failed ? get_exception_ptr_of(error_code::authentication_failed)
50-
: std::exception_ptr();
51+
: zk::exception_ptr();
5152

5253
for (auto& p : l_state_change_promises)
5354
{
@@ -105,7 +106,7 @@ static connection_params::host_list extract_host_list(string_view src)
105106
static bool extract_bool(string_view key, string_view val)
106107
{
107108
if (val.empty())
108-
throw std::invalid_argument(std::string("Key ") + std::string(key) + " has blank value");
109+
zk::throw_exception(std::invalid_argument(std::string("Key ") + std::string(key) + " has blank value"));
109110

110111
switch (val[0])
111112
{
@@ -118,20 +119,20 @@ static bool extract_bool(string_view key, string_view val)
118119
case 'F':
119120
return false;
120121
default:
121-
throw std::invalid_argument(std::string("Invalid value for ") + std::string(key) + std::string(" \"")
122+
zk::throw_exception(std::invalid_argument(std::string("Invalid value for ") + std::string(key) + std::string(" \"")
122123
+ std::string(val) + "\" -- expected a boolean"
123-
);
124+
));
124125
}
125126
}
126127

127128
static std::chrono::milliseconds extract_millis(string_view key, string_view val)
128129
{
129130
if (val.empty())
130-
throw std::invalid_argument(std::string("Key ") + std::string(key) + " has blank value");
131+
zk::throw_exception(std::invalid_argument(std::string("Key ") + std::string(key) + " has blank value"));
131132

132133
if (val[0] == 'P')
133134
{
134-
throw std::invalid_argument("ISO 8601 duration is not supported (yet).");
135+
zk::throw_exception(std::invalid_argument("ISO 8601 duration is not supported (yet)."));
135136
}
136137
else
137138
{
@@ -162,9 +163,9 @@ static void extract_advanced_options(string_view src, connection_params& out)
162163
{
163164
auto eq_it = std::find(qp_part.begin(), qp_part.end(), '=');
164165
if (eq_it == qp_part.end())
165-
throw std::invalid_argument("Invalid connection string -- query string must be specified as "
166+
zk::throw_exception(std::invalid_argument("Invalid connection string -- query string must be specified as "
166167
"\"key1=value1&key2=value2...\""
167-
);
168+
));
168169

169170
auto key = qp_part.substr(0, std::distance(qp_part.begin(), eq_it));
170171
auto val = qp_part.substr(std::distance(qp_part.begin(), eq_it) + 1);
@@ -180,7 +181,7 @@ static void extract_advanced_options(string_view src, connection_params& out)
180181
});
181182

182183
if (!invalid_keys_msg.empty())
183-
throw std::invalid_argument(std::move(invalid_keys_msg));
184+
zk::throw_exception(std::invalid_argument(std::move(invalid_keys_msg)));
184185
}
185186

186187
connection_params connection_params::parse(string_view conn_string)
@@ -195,9 +196,9 @@ connection_params connection_params::parse(string_view conn_string)
195196

196197
std::cmatch match;
197198
if (!std::regex_match(conn_string.begin(), conn_string.end(), match, expr))
198-
throw std::invalid_argument(std::string("Invalid connection string (") + std::string(conn_string)
199+
zk::throw_exception(std::invalid_argument(std::string("Invalid connection string (") + std::string(conn_string)
199200
+ " -- format is \"schema://[auth@]${host_addrs}/[path][?options]\""
200-
);
201+
));
201202

202203
connection_params out;
203204
out.connection_schema() = match[schema_idx].str();

src/zk/connection_zk.cpp

Lines changed: 15 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
#include "connection_zk.hpp"
2+
#include "exceptions.hpp"
23

34
#include <algorithm>
45
#include <cassert>
@@ -168,7 +169,7 @@ connection_zk::connection_zk(const connection_params& params) :
168169
_handle(nullptr)
169170
{
170171
if (params.connection_schema() != "zk")
171-
throw std::invalid_argument(std::string("Invalid connection string \"") + to_string(params) + "\"");
172+
zk::throw_exception(std::invalid_argument(std::string("Invalid connection string \"") + to_string(params) + "\""));
172173

173174
auto conn_string = [&] ()
174175
{
@@ -254,7 +255,7 @@ class connection_zk::basic_watcher :
254255
watcher::deliver_event(std::move(ev));
255256
}
256257

257-
void deliver_data(optional<TResult> data, std::exception_ptr ex_ptr)
258+
void deliver_data(optional<TResult> data, zk::exception_ptr ex_ptr)
258259
{
259260
if (!_data_delivered.exchange(true, std::memory_order_relaxed))
260261
{
@@ -378,7 +379,7 @@ class connection_zk::data_watcher :
378379
self.deliver_data(watch_result(get_result(buffer(data, data + data_sz), stat_from_raw(*pstat)),
379380
self.get_event_future()
380381
),
381-
std::exception_ptr()
382+
zk::exception_ptr()
382383
);
383384
}
384385
else
@@ -431,7 +432,7 @@ future<get_children_result> connection_zk::get_children(string_view path)
431432
}
432433
catch (...)
433434
{
434-
prom->set_exception(std::current_exception());
435+
prom->set_exception(zk::current_exception());
435436
}
436437
};
437438

@@ -482,12 +483,12 @@ class connection_zk::child_watcher :
482483
),
483484
self.get_event_future()
484485
),
485-
std::exception_ptr()
486+
zk::exception_ptr()
486487
);
487488
}
488489
catch (...)
489490
{
490-
self.deliver_data(nullopt, std::current_exception());
491+
self.deliver_data(nullopt, zk::current_exception());
491492
}
492493

493494
}
@@ -561,13 +562,13 @@ class connection_zk::exists_watcher :
561562
if (rc == error_code::ok)
562563
{
563564
self.deliver_data(watch_exists_result(exists_result(stat_from_raw(*stat_in)), self.get_event_future()),
564-
std::exception_ptr()
565+
zk::exception_ptr()
565566
);
566567
}
567568
else if (rc == error_code::no_entry)
568569
{
569570
self.deliver_data(watch_exists_result(exists_result(nullopt), self.get_event_future()),
570-
std::exception_ptr()
571+
zk::exception_ptr()
571572
);
572573
}
573574
else
@@ -853,12 +854,12 @@ struct connection_zk_commit_completer
853854
auto iter = std::partition_point(raw_results.begin(), raw_results.end(),
854855
[] (auto res) { return res.err == 0; }
855856
);
856-
throw transaction_failed(rc, std::size_t(std::distance(raw_results.begin(), iter)));
857+
zk::throw_exception(transaction_failed(rc, std::size_t(std::distance(raw_results.begin(), iter))));
857858
}
858859
}
859860
catch (...)
860861
{
861-
prom.set_exception(std::current_exception());
862+
prom.set_exception(zk::current_exception());
862863
}
863864
}
864865
};
@@ -944,9 +945,9 @@ future<multi_result> connection_zk::commit(multi_op&& txn_in)
944945
default:
945946
{
946947
using std::to_string;
947-
throw std::invalid_argument("Invalid op_type at index=" + to_string(idx) + ": "
948+
zk::throw_exception(std::invalid_argument("Invalid op_type at index=" + to_string(idx) + ": "
948949
+ to_string(src_op.type())
949-
);
950+
));
950951
}
951952
}
952953
}
@@ -972,7 +973,7 @@ future<multi_result> connection_zk::commit(multi_op&& txn_in)
972973
}
973974
catch (...)
974975
{
975-
pcompleter->prom.set_exception(std::current_exception());
976+
pcompleter->prom.set_exception(zk::current_exception());
976977
return pcompleter->prom.get_future();
977978
}
978979
}
@@ -990,7 +991,7 @@ future<void> connection_zk::load_fence()
990991
prom->set_exception(get_exception_ptr_of(rc));
991992
};
992993

993-
auto ppromise = std::make_unique<std::promise<void>>();
994+
auto ppromise = std::make_unique<zk::promise<void>>();
994995
auto rc = error_code_from_raw(::zoo_async(_handle, "/", callback, ppromise.get()));
995996
if (rc == error_code::ok)
996997
{

src/zk/error.cpp

Lines changed: 23 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
#include "error.hpp"
2+
#include "exceptions.hpp"
23

34
#include <sstream>
45
#include <ostream>
@@ -32,38 +33,38 @@ void throw_error(error_code code)
3233
{
3334
switch (code)
3435
{
35-
case error_code::connection_loss: throw connection_loss();
36-
case error_code::marshalling_error: throw marshalling_error();
37-
case error_code::not_implemented: throw not_implemented("unspecified");
38-
case error_code::invalid_arguments: throw invalid_arguments();
39-
case error_code::new_configuration_no_quorum: throw new_configuration_no_quorum();
40-
case error_code::reconfiguration_in_progress: throw reconfiguration_in_progress();
41-
case error_code::no_entry: throw no_entry();
42-
case error_code::not_authorized: throw not_authorized();
43-
case error_code::version_mismatch: throw version_mismatch();
44-
case error_code::no_children_for_ephemerals: throw no_children_for_ephemerals();
45-
case error_code::entry_exists: throw entry_exists();
46-
case error_code::not_empty: throw not_empty();
47-
case error_code::session_expired: throw session_expired();
48-
case error_code::authentication_failed: throw authentication_failed();
49-
case error_code::closed: throw closed();
50-
case error_code::read_only_connection: throw read_only_connection();
51-
case error_code::ephemeral_on_local_session: throw ephemeral_on_local_session();
52-
case error_code::reconfiguration_disabled: throw reconfiguration_disabled();
53-
case error_code::transaction_failed: throw transaction_failed(error_code::transaction_failed, 0U);
54-
default: throw error(code, "unknown");
36+
case error_code::connection_loss: zk::throw_exception( connection_loss() );
37+
case error_code::marshalling_error: zk::throw_exception( marshalling_error() );
38+
case error_code::not_implemented: zk::throw_exception( not_implemented("unspecified") );
39+
case error_code::invalid_arguments: zk::throw_exception( invalid_arguments() );
40+
case error_code::new_configuration_no_quorum: zk::throw_exception( new_configuration_no_quorum() );
41+
case error_code::reconfiguration_in_progress: zk::throw_exception( reconfiguration_in_progress() );
42+
case error_code::no_entry: zk::throw_exception( no_entry() );
43+
case error_code::not_authorized: zk::throw_exception( not_authorized() );
44+
case error_code::version_mismatch: zk::throw_exception( version_mismatch() );
45+
case error_code::no_children_for_ephemerals: zk::throw_exception( no_children_for_ephemerals() );
46+
case error_code::entry_exists: zk::throw_exception( entry_exists() );
47+
case error_code::not_empty: zk::throw_exception( not_empty() );
48+
case error_code::session_expired: zk::throw_exception( session_expired() );
49+
case error_code::authentication_failed: zk::throw_exception( authentication_failed() );
50+
case error_code::closed: zk::throw_exception( closed() );
51+
case error_code::read_only_connection: zk::throw_exception( read_only_connection() );
52+
case error_code::ephemeral_on_local_session: zk::throw_exception( ephemeral_on_local_session() );
53+
case error_code::reconfiguration_disabled: zk::throw_exception( reconfiguration_disabled() );
54+
case error_code::transaction_failed: zk::throw_exception( transaction_failed(error_code::transaction_failed, 0U) );
55+
default: zk::throw_exception( error(code, "unknown") );
5556
}
5657
}
5758

58-
std::exception_ptr get_exception_ptr_of(error_code code)
59+
zk::exception_ptr get_exception_ptr_of(error_code code)
5960
{
6061
try
6162
{
6263
throw_error(code);
6364
}
6465
catch (...)
6566
{
66-
return std::current_exception();
67+
return zk::current_exception();
6768
}
6869
}
6970

0 commit comments

Comments
 (0)