Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Enhancement: Reducing memory usage by removing the vtable in managed. #874

Closed
wants to merge 8 commits into from
8 changes: 6 additions & 2 deletions include/dpp/appcommand.h
Original file line number Diff line number Diff line change
Expand Up @@ -675,7 +675,7 @@ void from_json(const nlohmann::json& j, autocomplete_interaction& ai);
* into the events on_form_submit, on_slashcommand, on_user_context_menu,
* on_button_click, on_select_menu, etc.
*/
class DPP_EXPORT interaction : public managed, public json_interface<interaction> {
class DPP_EXPORT interaction : public managed<interaction>, public json_interface<interaction> {

/**
* @brief Get a resolved object from the resolved set
Expand Down Expand Up @@ -705,6 +705,7 @@ class DPP_EXPORT interaction : public managed, public json_interface<interaction
snowflake message_id; //!< Originating message id for context menu actions
permission app_permissions; //!< Permissions of the bot in the channel/guild where this command was issued
message msg; //!< Originating message for context menu actions
snowflake id; //! Unique identifier.
guild_member member; //!< Optional: guild member data for the invoking user, including permissions. Filled when the interaction is invoked in a guild
user usr; //!< User object for the invoking user
std::string token; //!< a continuation token for responding to the interaction
Expand Down Expand Up @@ -996,13 +997,16 @@ void to_json(nlohmann::json& j, const guild_command_permissions& gcp);
* @brief Represents an application command, created by your bot
* either globally, or on a guild.
*/
class DPP_EXPORT slashcommand : public managed, public json_interface<slashcommand> {
class DPP_EXPORT slashcommand : public managed<slashcommand>, public json_interface<slashcommand> {
public:
/**
* @brief Application id (usually matches your bots id)
*/
snowflake application_id;

/** Unique identifier */
snowflake id;

/**
* @brief Context menu type, defaults to dpp::ctxm_chat_input
*/
Expand Down
3 changes: 2 additions & 1 deletion include/dpp/application.h
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,7 @@ class DPP_EXPORT app_team {
/**
* @brief The application class represents details of a bot application
*/
class DPP_EXPORT application : public managed, public json_interface<application> {
class DPP_EXPORT application : public managed<application>, public json_interface<application> {
public:
std::string name; //!< the name of the app
utility::iconhash icon; //!< the icon hash of the app (may be empty)
Expand All @@ -139,6 +139,7 @@ class DPP_EXPORT application : public managed, public json_interface<application
application_install_params install_params; //!< Settings for the application's default in-app authorization link, if enabled
std::string custom_install_url; //!< The application's default custom authorization link, if enabled
std::string role_connections_verification_url; //!< The application's role connection verification entry point, which when configured will render the app as a verification method in the guild role verification configuration
snowflake id;

/** Constructor */
application();
Expand Down
2 changes: 1 addition & 1 deletion include/dpp/automod.h
Original file line number Diff line number Diff line change
Expand Up @@ -295,7 +295,7 @@ struct DPP_EXPORT automod_action : public json_interface<automod_action> {
/**
* @brief Represents an automod rule
*/
class DPP_EXPORT automod_rule : public managed, public json_interface<automod_rule> {
class DPP_EXPORT automod_rule : public managed<automod_rule>, public json_interface<automod_rule> {
public:
/**
* @brief the id of this rule
Expand Down
3 changes: 1 addition & 2 deletions include/dpp/cache.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,7 @@
#include <shared_mutex>

namespace dpp {

extern DPP_EXPORT std::unordered_map<managed*, time_t> deletion_queue;
extern DPP_EXPORT std::unordered_map<managed_base*, time_t> deletion_queue;
extern DPP_EXPORT std::mutex deletion_mutex;

/** forward declaration */
Expand Down
9 changes: 7 additions & 2 deletions include/dpp/channel.h
Original file line number Diff line number Diff line change
Expand Up @@ -197,13 +197,15 @@ struct DPP_EXPORT thread_member
/**
* @brief Represents a tag that is able to be applied to a thread in a forum or media channel
*/
struct DPP_EXPORT forum_tag : public managed, public json_interface<forum_tag> {
struct DPP_EXPORT forum_tag : public managed<forum_tag>, public json_interface<forum_tag> {
/** The name of the tag (0-20 characters) */
std::string name;
/** The emoji of the tag. Contains either nothing, the id of a guild's custom emoji or the unicode character of the emoji */
std::variant<std::monostate, snowflake, std::string> emoji;
/** Whether this tag can only be added to or removed from threads by a member with the `MANAGE_THREADS` permission */
bool moderated;
/** id of the channel the message was sent in */
snowflake id;

/** Constructor */
forum_tag();
Expand Down Expand Up @@ -254,11 +256,14 @@ typedef std::unordered_map<snowflake, thread_member> thread_member_map;
* There are one of these for every channel type except threads. Threads are
* special snowflakes. Get it? A Discord pun. Hahaha. .... I'll get my coat.
*/
class DPP_EXPORT channel : public managed, public json_interface<channel> {
class DPP_EXPORT channel : public managed<channel>, public json_interface<channel> {
public:
/** Channel name (1-100 characters) */
std::string name;

/** Unique identifier */
snowflake id;

/** Channel topic (0-4096 characters for forum and media channels, 0-1024 characters for all others) */
std::string topic;

Expand Down
4 changes: 3 additions & 1 deletion include/dpp/collector.h
Original file line number Diff line number Diff line change
Expand Up @@ -151,8 +151,10 @@ template<class T, class C> class collector
* @brief Represents a reaction.
* Can be filled for use in a collector
*/
class collected_reaction : public managed {
class collected_reaction : public managed<collected_reaction> {
public:
/// Unique identifier.
snowflake id;
/// Reacting user
user react_user;
/// Reacting guild
Expand Down
8 changes: 6 additions & 2 deletions include/dpp/emoji.h
Original file line number Diff line number Diff line change
Expand Up @@ -50,12 +50,16 @@ enum emoji_flags : uint8_t {
/**
* @brief Represents an emoji for a dpp::guild
*/
class DPP_EXPORT emoji : public managed, public json_interface<emoji> {
class DPP_EXPORT emoji : public managed<emoji>, public json_interface<emoji> {
public:
/**
* @brief Emoji name
*/
std::string name{};
/**
* @brief Unique identifier.
*/
snowflake id{};
/**
* @brief User id who uploaded the emoji
*/
Expand Down Expand Up @@ -100,7 +104,7 @@ class DPP_EXPORT emoji : public managed, public json_interface<emoji> {
/**
* @brief Destroy the emoji object
*/
~emoji() override = default;
~emoji() = default;

/**
* @brief Copy assignment operator, copies another emoji's data
Expand Down
13 changes: 10 additions & 3 deletions include/dpp/guild.h
Original file line number Diff line number Diff line change
Expand Up @@ -587,7 +587,7 @@ typedef std::unordered_map<snowflake, guild_member> members_container;
/**
* @brief Represents a guild on Discord (AKA a server)
*/
class DPP_EXPORT guild : public managed, public json_interface<guild> {
class DPP_EXPORT guild : public managed<guild>, public json_interface<guild> {
public:
/** Guild name */
std::string name;
Expand All @@ -609,6 +609,9 @@ class DPP_EXPORT guild : public managed, public json_interface<guild> {
/** List of channels on this server */
std::vector<snowflake> channels;

/** Unique identifier */
snowflake id{};

/** List of threads on this server */
std::vector<snowflake> threads;

Expand Down Expand Up @@ -1158,12 +1161,14 @@ enum onboarding_prompt_flags: uint8_t {
/**
* @brief Represents an onboarding prompt option
*/
struct DPP_EXPORT onboarding_prompt_option: public managed, public json_interface<onboarding_prompt_option> {
struct DPP_EXPORT onboarding_prompt_option: public managed<onboarding_prompt_option>, public json_interface<onboarding_prompt_option> {
std::vector<snowflake> channel_ids; //!< IDs for channels a member is added to when the option is selected
std::vector<snowflake> role_ids; //!< IDs for roles assigned to a member when the option is selected
dpp::emoji emoji; //!< Emoji of the option
std::string title; //!< Title of the option
std::string description; //!< Description of the option
/** Unique identifier */
snowflake id;

/**
* @brief Construct a new onboarding prompt option object
Expand Down Expand Up @@ -1219,11 +1224,13 @@ struct DPP_EXPORT onboarding_prompt_option: public managed, public json_interfac
/**
* @brief Represents an onboarding prompt
*/
struct DPP_EXPORT onboarding_prompt: public managed, public json_interface<onboarding_prompt> {
struct DPP_EXPORT onboarding_prompt: public managed<onboarding_prompt>, public json_interface<onboarding_prompt> {
onboarding_prompt_type type; //!< Type of prompt (defaults to dpp::opt_multiple_choice)
std::vector<onboarding_prompt_option> options; //!< Options available within the prompt
std::string title; //!< Title of the prompt
uint8_t flags; //!< A set of flags built from the bitmask defined by dpp::onboarding_prompt_flags
/** Unique identifier */
snowflake id;

/**
* @brief Construct a new onboarding prompt object
Expand Down
4 changes: 3 additions & 1 deletion include/dpp/integration.h
Original file line number Diff line number Diff line change
Expand Up @@ -80,8 +80,10 @@ struct DPP_EXPORT integration_app {
/**
* @brief Represents an integration on a guild, e.g. a connection to twitch.
*/
class DPP_EXPORT integration : public managed, public json_interface<integration> {
class DPP_EXPORT integration : public managed<integration>, public json_interface<integration> {
public:
//** Unique identifier */
snowflake id;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't really like this, it's basically added tons of duplicate lines to every object to save 8 bytes of ram per instance, I think readability is more important in this case

/** Integration name */
std::string name;
/** Integration type */
Expand Down
35 changes: 20 additions & 15 deletions include/dpp/managed.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,34 +26,35 @@

namespace dpp {

class managed_base {};

/** @brief The managed class is the base class for various types that can
* be stored in a cache that are identified by a dpp::snowflake id.
*/
class DPP_EXPORT managed {
template<typename derived_type> class managed : public managed_base {
public:
/**
* @brief Unique ID of object set by Discord.
* This value contains a timestamp, worker ID, internal server ID, and an incrementing value.
* Only the timestamp is relevant to us as useful metadata.
*/
snowflake id;
/*
* @brief Default constructor.
*/
inline managed() noexcept = default;

/**
* @brief Constructor, initialises ID
* @param nid ID to set
*/
managed(const snowflake nid = 0);
/**
* @brief Destroy the managed object
*/
virtual ~managed() = default;
inline managed(const snowflake nid) {
static_cast<derived_type*>(this)->id = nid;
}

/**
* @brief Get the creation time of this object according to Discord.
*
* @return double creation time inferred from the snowflake ID.
* The minimum possible value is the first second of 2015.
*/
double get_creation_time() const;
inline double get_creation_time() const {
return static_cast<const derived_type*>(this)->id.get_creation_time();
}

/**
* @brief Comparison operator for comparing two managed objects by id
Expand All @@ -62,7 +63,9 @@ namespace dpp {
* @return true objects are the same id
* @return false objects are not the same id
*/
bool operator==(const managed& other) const noexcept;
inline bool operator==(const managed& other) const noexcept {
return static_cast<const derived_type*>(this)->id == static_cast<const derived_type*>(&other)->id;
}

/**
* @brief Comparison operator for comparing two managed objects by id
Expand All @@ -71,7 +74,9 @@ namespace dpp {
* @return true objects are not the same id
* @return false objects are the same id
*/
bool operator!=(const managed& other) const noexcept;
inline bool operator!=(const managed& other) const noexcept {
return static_cast<const derived_type*>(this)->id != static_cast<const derived_type*>(&other)->id;
}
};

} // namespace dpp
12 changes: 9 additions & 3 deletions include/dpp/message.h
Original file line number Diff line number Diff line change
Expand Up @@ -874,7 +874,7 @@ enum sticker_format : uint8_t {
/**
* @brief Represents stickers received in messages
*/
struct DPP_EXPORT sticker : public managed, public json_interface<sticker> {
struct DPP_EXPORT sticker : public managed<sticker>, public json_interface<sticker> {
/** Optional: for standard stickers, id of the pack the sticker is from
*/
snowflake pack_id;
Expand All @@ -893,6 +893,8 @@ struct DPP_EXPORT sticker : public managed, public json_interface<sticker> {
* here in the library.
*/
std::string asset;
/** Unique identifier */
snowflake id;
/** The type of sticker */
sticker_type type;
/// type of sticker format
Expand Down Expand Up @@ -957,7 +959,7 @@ struct DPP_EXPORT sticker : public managed, public json_interface<sticker> {
/**
* @brief Represents a sticker pack (the built in groups of stickers that all nitro users get to use)
*/
struct DPP_EXPORT sticker_pack : public managed, public json_interface<sticker_pack> {
struct DPP_EXPORT sticker_pack : public managed<sticker_pack>, public json_interface<sticker_pack> {
/// the stickers in the pack
std::map<snowflake, sticker> stickers;
/// name of the sticker pack
Expand All @@ -970,6 +972,8 @@ struct DPP_EXPORT sticker_pack : public managed, public json_interface<sticker_p
std::string description;
/// id of the sticker pack's banner image
snowflake banner_asset_id;
/** Unique identifier */
snowflake id;

/**
* @brief Construct a new sticker pack object
Expand Down Expand Up @@ -1177,7 +1181,9 @@ struct DPP_EXPORT cache_policy_t {
/**
* @brief Represents messages sent and received on Discord
*/
struct DPP_EXPORT message : public managed {
struct DPP_EXPORT message : public managed<message> {
/** Unique identifier */
snowflake id;
/** id of the channel the message was sent in */
snowflake channel_id;
/** Optional: id of the guild the message was sent in */
Expand Down
6 changes: 5 additions & 1 deletion include/dpp/role.h
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ enum role_flags : uint8_t {
* ID as the guild's ID. This is the base permission set applied to all users where no other role or override
* applies, and is the starting value of the bit mask looped through to calculate channel permissions.
*/
class DPP_EXPORT role : public managed, public json_interface<role> {
class DPP_EXPORT role : public managed<role>, public json_interface<role> {
public:
/**
* @brief Role name
Expand All @@ -60,6 +60,10 @@ class DPP_EXPORT role : public managed, public json_interface<role> {
* @brief Guild ID
*/
snowflake guild_id;

/** Unique identifier */
snowflake id;

/**
* @brief Role colour.
* A colour of 0 means no colour. If you want a black role,
Expand Down
3 changes: 2 additions & 1 deletion include/dpp/scheduled_event.h
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,8 @@ struct DPP_EXPORT event_member {
/**
* @brief A scheduled event
*/
struct DPP_EXPORT scheduled_event : public managed, public json_interface<scheduled_event> {
struct DPP_EXPORT scheduled_event : public managed<scheduled_event>, public json_interface<scheduled_event> {
snowflake id; //! Unique identifier
snowflake guild_id; //!< the guild id which the scheduled event belongs to
snowflake channel_id; //!< the channel id in which the scheduled event will be hosted, or null if scheduled entity type is EXTERNAL (may be empty)
snowflake creator_id; //!< Optional: the id of the user that created the scheduled event
Expand Down
4 changes: 3 additions & 1 deletion include/dpp/stage_instance.h
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ enum stage_privacy_level : uint8_t {
* @brief A stage instance.
* Stage instances are like a conference facility, with moderators/speakers and listeners.
*/
struct DPP_EXPORT stage_instance : public managed, public json_interface<stage_instance> {
struct DPP_EXPORT stage_instance : public managed<stage_instance>, public json_interface<stage_instance> {
/// The guild id of the associated Stage channel
snowflake guild_id;
/// The id of the associated Stage channel
Expand All @@ -54,6 +54,8 @@ struct DPP_EXPORT stage_instance : public managed, public json_interface<stage_i
stage_privacy_level privacy_level;
/// Whether or not Stage Discovery is disabled
bool discoverable_disabled;
/** Unique identifier */
snowflake id;

/**
* @brief Create a stage_instance object
Expand Down
4 changes: 3 additions & 1 deletion include/dpp/user.h
Original file line number Diff line number Diff line change
Expand Up @@ -85,14 +85,16 @@ enum user_flags : uint32_t {
/**
* @brief Represents a user on discord. May or may not be a member of a dpp::guild.
*/
class DPP_EXPORT user : public managed, public json_interface<user> {
class DPP_EXPORT user : public managed<user>, public json_interface<user> {
public:
/** Discord username */
std::string username;
/** Global display name */
std::string global_name;
/** Avatar hash */
utility::iconhash avatar;
/** Unique identifier */
snowflake id;
/** Avatar decoration hash */
utility::iconhash avatar_decoration;
/** Flags built from a bitmask of values in dpp::user_flags */
Expand Down
Loading
Loading