Always use struct

This commit is contained in:
2025-08-23 06:10:55 -04:00
parent b86cf3680e
commit 4af5e0423e
14 changed files with 56 additions and 41 deletions

View File

@@ -83,7 +83,7 @@
* @warning Do not share ArenaAllocator instances between threads. Use separate * @warning Do not share ArenaAllocator instances between threads. Use separate
* instances per thread or per logical unit of work. * instances per thread or per logical unit of work.
*/ */
class ArenaAllocator { struct ArenaAllocator {
private: private:
/** /**
* @brief Internal block structure for the intrusive linked list. * @brief Internal block structure for the intrusive linked list.

View File

@@ -60,7 +60,7 @@ struct Operation {
* memory management and ownership. This class has no knowledge of any * memory management and ownership. This class has no knowledge of any
* specific serialization formats or encoding schemes. * specific serialization formats or encoding schemes.
*/ */
class CommitRequest { struct CommitRequest {
private: private:
ArenaAllocator arena_; ArenaAllocator arena_;
std::optional<std::string_view> request_id_; std::optional<std::string_view> request_id_;

View File

@@ -13,7 +13,7 @@
* and streaming parsing (for incremental data processing). This allows * and streaming parsing (for incremental data processing). This allows
* efficient handling of network protocols where data may arrive in chunks. * efficient handling of network protocols where data may arrive in chunks.
*/ */
class CommitRequestParser { struct CommitRequestParser {
public: public:
/** /**
* @brief Status returned by streaming parse operations. * @brief Status returned by streaming parse operations.

View File

@@ -83,7 +83,7 @@ struct Config {
* auto config2 = ConfigParser::parse_toml_string(toml); * auto config2 = ConfigParser::parse_toml_string(toml);
* ``` * ```
*/ */
class ConfigParser { struct ConfigParser {
public: public:
/** /**
* @brief Load configuration from a TOML file. * @brief Load configuration from a TOML file.

View File

@@ -1,11 +1,13 @@
#include "connection.hpp" #include "connection.hpp"
#include "server.hpp" // Need this for releaseBackToServer implementation
#include <climits> #include <climits>
#include <cstdio> #include <cstdio>
#include <cstdlib> #include <cstdlib>
#include <errno.h> #include <errno.h>
#include <limits.h> #include <limits.h>
#include "server.hpp" // Need this for releaseBackToServer implementation
// Static thread-local storage for iovec buffer // Static thread-local storage for iovec buffer
static thread_local std::vector<struct iovec> g_iovec_buffer{IOV_MAX}; static thread_local std::vector<struct iovec> g_iovec_buffer{IOV_MAX};

View File

@@ -1,7 +1,5 @@
#pragma once #pragma once
#include "arena_allocator.hpp"
#include "connection_handler.hpp"
#include <cassert> #include <cassert>
#include <cstring> #include <cstring>
#include <deque> #include <deque>
@@ -10,6 +8,9 @@
#include <sys/uio.h> #include <sys/uio.h>
#include <unistd.h> #include <unistd.h>
#include "arena_allocator.hpp"
#include "connection_handler.hpp"
#ifndef __has_feature #ifndef __has_feature
#define __has_feature(x) 0 #define __has_feature(x) 0
#endif #endif
@@ -39,7 +40,7 @@
* private. * private.
*/ */
// Forward declaration // Forward declaration
class Server; struct Server;
struct Connection { struct Connection {
// No public constructor or factory method - only Server can create // No public constructor or factory method - only Server can create
@@ -305,7 +306,7 @@ struct Connection {
private: private:
// Server is a friend and can access all networking internals // Server is a friend and can access all networking internals
friend class Server; friend struct Server;
/** /**
* @brief Private constructor - only accessible by Server. * @brief Private constructor - only accessible by Server.

View File

@@ -17,7 +17,7 @@ struct Connection;
* The networking layer manages connection lifecycle, I/O multiplexing, * The networking layer manages connection lifecycle, I/O multiplexing,
* and efficient data transfer, while handlers focus purely on protocol logic. * and efficient data transfer, while handlers focus purely on protocol logic.
*/ */
class ConnectionHandler { struct ConnectionHandler {
public: public:
virtual ~ConnectionHandler() = default; virtual ~ConnectionHandler() = default;

View File

@@ -16,7 +16,7 @@ struct Connection;
* allocated on-demand as connections are created. * allocated on-demand as connections are created.
* *
*/ */
class ConnectionRegistry { struct ConnectionRegistry {
public: public:
/** /**
* Initialize the connection registry. * Initialize the connection registry.

View File

@@ -1,14 +1,16 @@
#pragma once #pragma once
#include <memory>
#include <string_view>
#include <thread>
#include <llhttp.h>
#include "connection.hpp" #include "connection.hpp"
#include "connection_handler.hpp" #include "connection_handler.hpp"
#include "perfetto_categories.hpp" #include "perfetto_categories.hpp"
#include "server.hpp" #include "server.hpp"
#include "thread_pipeline.hpp" #include "thread_pipeline.hpp"
#include <llhttp.h>
#include <memory>
#include <string_view>
#include <thread>
/** /**
* HTTP routes supported by WeaselDB server. * HTTP routes supported by WeaselDB server.
@@ -60,14 +62,7 @@ struct HttpConnectionState {
* HTTP/1.1 server implementation using llhttp for parsing. * HTTP/1.1 server implementation using llhttp for parsing.
* Supports the WeaselDB REST API endpoints with enum-based routing. * Supports the WeaselDB REST API endpoints with enum-based routing.
*/ */
class HttpHandler : public ConnectionHandler { struct HttpHandler : ConnectionHandler {
static constexpr int kFinalStageThreads = 2;
static constexpr int kLogSize = 12;
ThreadPipeline<std::unique_ptr<Connection>> pipeline{kLogSize,
{kFinalStageThreads}};
std::vector<std::thread> finalStageThreads;
public:
HttpHandler() { HttpHandler() {
for (int threadId = 0; threadId < kFinalStageThreads; ++threadId) { for (int threadId = 0; threadId < kFinalStageThreads; ++threadId) {
finalStageThreads.emplace_back([this, threadId]() { finalStageThreads.emplace_back([this, threadId]() {
@@ -124,6 +119,12 @@ public:
static int onMessageComplete(llhttp_t *parser); static int onMessageComplete(llhttp_t *parser);
private: private:
static constexpr int kFinalStageThreads = 2;
static constexpr int kLogSize = 12;
ThreadPipeline<std::unique_ptr<Connection>> pipeline{kLogSize,
{kFinalStageThreads}};
std::vector<std::thread> finalStageThreads;
// Route handlers // Route handlers
void handleGetVersion(Connection &conn, const HttpConnectionState &state); void handleGetVersion(Connection &conn, const HttpConnectionState &state);
void handlePostCommit(Connection &conn, const HttpConnectionState &state); void handlePostCommit(Connection &conn, const HttpConnectionState &state);

View File

@@ -12,7 +12,7 @@
* This parser uses the weaseljson library to parse JSON-formatted * This parser uses the weaseljson library to parse JSON-formatted
* commit requests into CommitRequest objects. * commit requests into CommitRequest objects.
*/ */
class JsonCommitRequestParser : public CommitRequestParser { struct JsonCommitRequestParser : CommitRequestParser {
public: public:
// Parser state // Parser state
enum class ParseState { enum class ParseState {

View File

@@ -33,7 +33,7 @@ struct JsonToken {
* } * }
* ``` * ```
*/ */
class PerfectHash { struct PerfectHash {
public: public:
/** /**
* @brief Look up a JSON token by name using perfect hash. * @brief Look up a JSON token by name using perfect hash.

View File

@@ -1,6 +1,5 @@
#include "server.hpp" #include "server.hpp"
#include "connection.hpp"
#include "connection_registry.hpp"
#include <csignal> #include <csignal>
#include <cstdio> #include <cstdio>
#include <cstdlib> #include <cstdlib>
@@ -17,6 +16,9 @@
#include <unistd.h> #include <unistd.h>
#include <vector> #include <vector>
#include "connection.hpp"
#include "connection_registry.hpp"
// Static thread-local storage for read buffer (used across different functions) // Static thread-local storage for read buffer (used across different functions)
static thread_local std::vector<char> g_read_buffer; static thread_local std::vector<char> g_read_buffer;

View File

@@ -1,14 +1,15 @@
#pragma once #pragma once
#include "config.hpp"
#include "connection_handler.hpp"
#include "connection_registry.hpp"
#include <atomic> #include <atomic>
#include <memory> #include <memory>
#include <span> #include <span>
#include <thread> #include <thread>
#include <vector> #include <vector>
#include "config.hpp"
#include "connection_handler.hpp"
#include "connection_registry.hpp"
/** /**
* High-performance multi-threaded server for handling network connections. * High-performance multi-threaded server for handling network connections.
* *
@@ -32,8 +33,7 @@
* - Prevention of accidental stack allocation that would break safety * - Prevention of accidental stack allocation that would break safety
* guarantees * guarantees
*/ */
class Server : public std::enable_shared_from_this<Server> { struct Server : std::enable_shared_from_this<Server> {
public:
/** /**
* Factory method to create a Server instance. * Factory method to create a Server instance.
* *

View File

@@ -72,13 +72,22 @@ void add_block(size_t size);
uint32_t initial_block_size_; uint32_t initial_block_size_;
``` ```
### Classes and Structs ### Structs
- **PascalCase** for class and struct names - **PascalCase** for struct names
- **Prefer struct over class** - public members at the top, avoid `class { public:` pattern - **Always use struct** - eliminates debates about complexity and maintains consistency
- **Public members first, private after** - leverages struct's default public access
- Use `private:` sections when encapsulation is needed
```cpp ```cpp
struct ArenaAllocator {}; struct ArenaAllocator {
struct CommitRequest {}; // Public interface first
struct JsonCommitRequestParser {}; explicit ArenaAllocator(size_t initial_size = 1024);
void* allocate_raw(size_t size);
private:
// Private members after
uint32_t initial_block_size_;
Block* current_block_;
};
``` ```
### Enums ### Enums
@@ -173,8 +182,8 @@ std::unique_ptr<Parser> parser;
## Code Structure ## Code Structure
### Class Design ### Struct Design
- **Move-only semantics** for resource-owning classes - **Move-only semantics** for resource-owning structs
- **Explicit constructors** to prevent implicit conversions - **Explicit constructors** to prevent implicit conversions
- **Delete copy operations** when inappropriate - **Delete copy operations** when inappropriate
```cpp ```cpp
@@ -308,7 +317,7 @@ static_assert(std::is_trivially_destructible_v<T>, "Arena requires trivially des
## Documentation ## Documentation
### Doxygen Style ### Doxygen Style
- **/** for class and public method documentation - **/** for struct and public method documentation
- **@brief** for short descriptions - **@brief** for short descriptions
- **@param** and **@return** for function parameters - **@param** and **@return** for function parameters
- **@note** for important implementation notes - **@note** for important implementation notes