Skip to content

Commit f452c87

Browse files
committed
Update test and make lookup and update more thread-safe.
1 parent 5fbc670 commit f452c87

File tree

3 files changed

+40
-23
lines changed

3 files changed

+40
-23
lines changed

http/src/http/server/simple_sessions.cpp

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
namespace network {
1111
namespace http {
1212

13-
session& simple_sessions::lookup(boost::string_ref session_id) {
13+
session simple_sessions::lookup(boost::string_ref session_id) {
1414
std::string real_session_id =
1515
session_id.empty() ? std::to_string(next_session_id_.fetch_add(
1616
1, std::memory_order::memory_order_seq_cst)) :
@@ -26,5 +26,23 @@ session& simple_sessions::lookup(boost::string_ref session_id) {
2626
return result.first->second;
2727
}
2828

29+
void simple_sessions::update(boost::string_ref session_id, session&& session) {
30+
std::string real_session_id =
31+
session_id.empty() ? std::to_string(next_session_id_.fetch_add(
32+
1, std::memory_order::memory_order_seq_cst)) :
33+
static_cast<std::string>(session_id);
34+
assert(real_session_id != "");
35+
std::lock_guard<std::mutex> lock_sessions(sessions_mutex_);
36+
auto it = sessions_.find(real_session_id);
37+
if (it != sessions_.end()) {
38+
it->second = session;
39+
} else {
40+
bool added = false;
41+
std::tie(it, added) = sessions_.insert(make_pair(std::move(real_session_id),
42+
session));
43+
assert(added && " -- for some reason we cannot add here.");
44+
}
45+
}
46+
2947
} // namespace http
3048
} // namespace network

http/src/http/server/simple_sessions.hpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,8 @@ struct simple_sessions {
2323
simple_sessions& operator=(const simple_sessions&) = delete;
2424
simple_sessions& operator=(simple_sessions&) = delete;
2525

26-
session &lookup(boost::string_ref session_id);
26+
session lookup(boost::string_ref session_id);
27+
void update(boost::string_ref session_id, session&& session);
2728
private:
2829
typedef std::unordered_map<std::string, session> session_map_type;
2930
std::mutex sessions_mutex_;

http/test/server_simple_sessions_test.cpp

Lines changed: 19 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
#include <gtest/gtest.h>
88
#include <http/server/simple_sessions.hpp>
99
#include <future>
10+
#include <map>
1011

1112
namespace http = network::http;
1213
namespace net = network;
@@ -20,42 +21,39 @@ TEST(simple_sessions_test, constructor) {
2021

2122
TEST(simple_sessions_test, lookup) {
2223
http::simple_sessions simple_sessions;
23-
http::session &session = simple_sessions.lookup("sessionid");
24+
http::session session = simple_sessions.lookup("sessionid");
2425
(void) session;
2526
}
2627

2728
TEST(simple_sessions_test, update) {
2829
http::simple_sessions simple_sessions;
2930
{
30-
http::session &session = simple_sessions.lookup("sessionid");
31+
http::session session = simple_sessions.lookup("sessionid");
3132
session.set("user", "some-user");
33+
simple_sessions.update("sessionid", std::move(session));
3234
}
3335
{
34-
http::session &session = simple_sessions.lookup("sessionid");
36+
http::session session = simple_sessions.lookup("sessionid");
3537
EXPECT_EQ("some-user", session["user"]);
3638
}
3739
}
3840

3941
TEST(simple_sessions_test, threaded_sessions) {
4042
http::simple_sessions simple_sessions;
41-
auto f0 = std::async([&]() {
42-
http::session &session = simple_sessions.lookup("");
43-
return session["id"];
44-
});
45-
auto f1 = std::async([&]() {
46-
http::session &session = simple_sessions.lookup("");
47-
return session["id"];
48-
});
49-
auto f2 = std::async([&]() {
50-
http::session &session = simple_sessions.lookup("");
51-
return session["id"];
52-
});
53-
std::string session0 = f0.get(),
54-
session1 = f1.get(),
55-
session2 = f2.get();
56-
EXPECT_NE(session0, session1);
57-
EXPECT_NE(session1, session2);
58-
EXPECT_NE(session0, session2);
43+
// Run many asynchronous functions (hoping that there will be many threads
44+
// created) so that we may be able to exercise the atomics and the
45+
// concurrency of the simple session manager.
46+
std::vector<std::future<std::string>> futures;
47+
constexpr size_t max_sessions = 1000;
48+
for (size_t counter = 0; counter < max_sessions; ++counter) {
49+
futures.emplace_back(std::async(std::launch::async, [&]() {
50+
return simple_sessions.lookup("")["id"];
51+
}));
52+
}
53+
std::set<std::string> ids;
54+
for (auto &future : futures)
55+
ids.emplace(future.get());
56+
EXPECT_EQ(max_sessions, ids.size());
5957
}
6058

6159
} // namespace

0 commit comments

Comments
 (0)