Skip to content

Commit 5c67f8f

Browse files
committed
replaced libpq pointers with safe unique ptrs
1 parent 3ae20bd commit 5c67f8f

File tree

5 files changed

+41
-23
lines changed

5 files changed

+41
-23
lines changed

source/async_postgres.hpp

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
#pragma once
2-
32
#include <GarrysMod/Lua/AutoReference.h>
43
#include <GarrysMod/Lua/Interface.h>
54
#include <GarrysMod/Lua/LuaInterface.h>
@@ -15,6 +14,8 @@
1514
#include <variant>
1615
#include <vector>
1716

17+
#include "safe_pg.hpp"
18+
1819
namespace GLua = GarrysMod::Lua;
1920

2021
#define lua_interface() \
@@ -68,17 +69,15 @@ namespace async_postgres {
6869
PostgresPollingStatusType status = PGRES_POLLING_WRITING;
6970
};
7071

71-
using PGconnPtr = std::unique_ptr<PGconn, decltype(&PQfinish)>;
72-
7372
struct Connection {
74-
PGconnPtr conn;
73+
pg::conn conn;
7574
GLua::AutoReference lua_table;
7675
std::queue<Query> queries;
7776
std::optional<ResetEvent> reset_event;
7877
bool receive_notifications =
7978
false; // enabled if on_notify lua field is set
8079

81-
Connection(GLua::ILuaInterface* lua, PGconnPtr&& conn);
80+
Connection(GLua::ILuaInterface* lua, pg::conn&& conn);
8281
~Connection();
8382
};
8483

source/connection.cpp

Lines changed: 6 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ using namespace async_postgres;
44

55
std::vector<Connection*> async_postgres::connections = {};
66

7-
Connection::Connection(GLua::ILuaInterface* lua, PGconnPtr&& conn)
7+
Connection::Connection(GLua::ILuaInterface* lua, pg::conn&& conn)
88
: conn(std::move(conn)) {
99
lua->CreateTable();
1010
this->lua_table = GLua::AutoReference(lua);
@@ -20,7 +20,7 @@ Connection::~Connection() {
2020
}
2121

2222
struct ConnectionEvent {
23-
PGconnPtr conn;
23+
pg::conn conn;
2424
GLua::AutoReference callback;
2525
PostgresPollingStatusType status = PGRES_POLLING_WRITING;
2626
bool is_reset = false;
@@ -40,17 +40,16 @@ inline bool socket_is_ready(PGconn* conn, PostgresPollingStatusType status) {
4040

4141
void async_postgres::connect(GLua::ILuaInterface* lua, std::string_view url,
4242
GLua::AutoReference&& callback) {
43-
auto conn = PGconnPtr(PQconnectStart(url.data()), &PQfinish);
44-
auto conn_ptr = conn.get();
43+
auto conn = pg::connectStart(url);
4544

4645
if (!conn) {
4746
// funnily enough, this probably will instead throw a std::bad_alloc
4847
throw std::runtime_error("failed to allocate connection");
4948
}
5049

51-
if (PQstatus(conn_ptr) == CONNECTION_BAD ||
52-
PQsetnonblocking(conn_ptr, 1) != 0) {
53-
throw std::runtime_error(PQerrorMessage(conn_ptr));
50+
if (PQstatus(conn.get()) == CONNECTION_BAD ||
51+
PQsetnonblocking(conn.get(), 1) != 0) {
52+
throw std::runtime_error(PQerrorMessage(conn.get()));
5453
}
5554

5655
auto event = ConnectionEvent{std::move(conn), std::move(callback)};
@@ -65,8 +64,6 @@ inline bool poll_pending_connection(GLua::ILuaInterface* lua,
6564
return false;
6665
}
6766

68-
// TODO: handle reset
69-
7067
event.status = PQconnectPoll(event.conn.get());
7168
if (event.status == PGRES_POLLING_OK) {
7269
auto state = new Connection(lua, std::move(event.conn));

source/notifications.cpp

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -33,16 +33,13 @@ void async_postgres::process_notifications(GLua::ILuaInterface* lua,
3333
return;
3434
}
3535

36-
PGnotify* notify;
37-
while ((notify = PQnotifies(state->conn.get()))) {
36+
while (auto notify = pg::getNotify(state->conn)) {
3837
if (push_on_notify(lua, state)) {
3938
lua->PushString(notify->relname); // arg 1 channel name
4039
lua->PushString(notify->extra); // arg 2 payload
4140
lua->PushNumber(notify->be_pid); // arg 3 backend pid
4241

4342
pcall(lua, 3, 0);
4443
}
45-
46-
PQfreemem(notify);
4744
}
4845
}

source/query.cpp

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,7 @@ void async_postgres::process_queries(GLua::ILuaInterface* lua,
9999
}
100100

101101
while (PQisBusy(state->conn.get()) == 0) {
102-
auto* result = PQgetResult(state->conn.get());
102+
auto result = pg::getResult(state->conn);
103103
if (!result) {
104104
// query is done
105105
state->queries.pop();
@@ -108,16 +108,15 @@ void async_postgres::process_queries(GLua::ILuaInterface* lua,
108108

109109
if (query.callback) {
110110
query.callback.Push();
111-
if (!bad_result(result)) {
111+
if (!bad_result(result.get())) {
112112
lua->PushBool(true);
113-
create_result_table(lua, result);
113+
create_result_table(lua, result.get());
114114
} else {
115115
lua->PushBool(false);
116-
lua->PushString(PQresultErrorMessage(result));
116+
lua->PushString(PQresultErrorMessage(result.get()));
117117
}
118118

119119
pcall(lua, 2, 0);
120120
}
121-
PQclear(result);
122121
}
123122
}

source/safe_pg.hpp

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
#pragma once
2+
3+
#include <libpq-fe.h>
4+
5+
#include <memory>
6+
#include <string_view>
7+
8+
/// Just small wrappers around libpq types to not have to deal with freeing them
9+
/// manually.
10+
namespace async_postgres::pg {
11+
using conn = std::unique_ptr<PGconn, decltype(&PQfinish)>;
12+
using result = std::unique_ptr<PGresult, decltype(&PQclear)>;
13+
using notify = std::unique_ptr<PGnotify, decltype(&PQfreemem)>;
14+
15+
inline conn connectStart(std::string_view conninfo) {
16+
return conn(PQconnectStart(conninfo.data()), &PQfinish);
17+
}
18+
19+
inline result getResult(conn& conn) {
20+
return result(PQgetResult(conn.get()), &PQclear);
21+
}
22+
23+
inline notify getNotify(conn& conn) {
24+
return notify(PQnotifies(conn.get()), &PQfreemem);
25+
}
26+
} // namespace async_postgres::pg

0 commit comments

Comments
 (0)