Song: embed the Tag object statically into class Song

Reduces overhead because we need to manage only one memory allocation.
According to valgrind/massif, we save 7%.
This commit is contained in:
Max Kellermann 2014-01-18 19:08:39 +01:00
parent bc966577ff
commit d2cf74027c
14 changed files with 26 additions and 47 deletions

View File

@ -39,9 +39,7 @@ typedef std::set<const char *, StringLess> StringSet;
static bool static bool
CollectTags(StringSet &set, TagType tag_type, Song &song) CollectTags(StringSet &set, TagType tag_type, Song &song)
{ {
Tag *tag = song.tag; const Tag *tag = &song.tag;
if (tag == nullptr)
return true;
bool found = false; bool found = false;
for (unsigned i = 0; i < tag->num_items; ++i) { for (unsigned i = 0; i < tag->num_items; ++i) {
@ -108,8 +106,7 @@ StatsVisitSong(DatabaseStats &stats, StringSet &artists, StringSet &albums,
{ {
++stats.song_count; ++stats.song_count;
if (song.tag != nullptr) StatsVisitTag(stats, artists, albums, song.tag);
StatsVisitTag(stats, artists, albums, *song.tag);
return true; return true;
} }

View File

@ -70,7 +70,7 @@ PrintSongBrief(Client &client, const Song &song)
{ {
song_print_uri(client, song); song_print_uri(client, song);
if (song.tag != nullptr && song.tag->has_playlist) if (song.tag.has_playlist)
/* this song file has an embedded CUE sheet */ /* this song file has an embedded CUE sheet */
print_playlist_in_directory(client, song.parent, song.uri); print_playlist_in_directory(client, song.parent, song.uri);
@ -82,7 +82,7 @@ PrintSongFull(Client &client, const Song &song)
{ {
song_print_info(client, song); song_print_info(client, song);
if (song.tag != nullptr && song.tag->has_playlist) if (song.tag.has_playlist)
/* this song file has an embedded CUE sheet */ /* this song file has an embedded CUE sheet */
print_playlist_in_directory(client, song.parent, song.uri); print_playlist_in_directory(client, song.parent, song.uri);

View File

@ -25,7 +25,7 @@
DetachedSong::DetachedSong(const Song &other) DetachedSong::DetachedSong(const Song &other)
:uri(other.GetURI().c_str()), :uri(other.GetURI().c_str()),
tag(other.tag != nullptr ? *other.tag : Tag()), tag(other.tag),
mtime(other.mtime), mtime(other.mtime),
start_ms(other.start_ms), end_ms(other.end_ms) {} start_ms(other.start_ms), end_ms(other.end_ms) {}

View File

@ -49,9 +49,7 @@ UpdatePlaylistSong(const Database &db, DetachedSong &song)
} }
song.SetLastModified(original->mtime); song.SetLastModified(original->mtime);
song.SetTag(original->tag);
if (original->tag != nullptr)
song.SetTag(*original->tag);
db.ReturnSong(original); db.ReturnSong(original);
return true; return true;

View File

@ -29,14 +29,13 @@
#include <stdlib.h> #include <stdlib.h>
inline Song::Song(const char *_uri, size_t uri_length, Directory *_parent) inline Song::Song(const char *_uri, size_t uri_length, Directory *_parent)
:tag(nullptr), parent(_parent), mtime(0), start_ms(0), end_ms(0) :parent(_parent), mtime(0), start_ms(0), end_ms(0)
{ {
memcpy(uri, _uri, uri_length + 1); memcpy(uri, _uri, uri_length + 1);
} }
inline Song::~Song() inline Song::~Song()
{ {
delete tag;
} }
static Song * static Song *
@ -57,7 +56,7 @@ Song *
Song::NewFrom(DetachedSong &&other, Directory *parent) Song::NewFrom(DetachedSong &&other, Directory *parent)
{ {
Song *song = song_alloc(other.GetURI(), parent); Song *song = song_alloc(other.GetURI(), parent);
song->tag = new Tag(std::move(other.WritableTag())); song->tag = std::move(other.WritableTag());
song->mtime = other.GetLastModified(); song->mtime = other.GetLastModified();
song->start_ms = other.GetStartMS(); song->start_ms = other.GetStartMS();
song->end_ms = other.GetEndMS(); song->end_ms = other.GetEndMS();
@ -101,8 +100,8 @@ Song::GetDuration() const
if (end_ms > 0) if (end_ms > 0)
return (end_ms - start_ms) / 1000.0; return (end_ms - start_ms) / 1000.0;
if (tag == nullptr) if (tag.time <= 0)
return 0; return 0;
return tag->time - start_ms / 1000.0; return tag.time - start_ms / 1000.0;
} }

View File

@ -21,6 +21,7 @@
#define MPD_SONG_HXX #define MPD_SONG_HXX
#include "util/list.h" #include "util/list.h"
#include "tag/Tag.hxx"
#include "Compiler.h" #include "Compiler.h"
#include <string> #include <string>
@ -31,7 +32,6 @@
#define SONG_FILE "file: " #define SONG_FILE "file: "
#define SONG_TIME "Time: " #define SONG_TIME "Time: "
struct Tag;
struct Directory; struct Directory;
class DetachedSong; class DetachedSong;
@ -49,7 +49,7 @@ struct Song {
*/ */
struct list_head siblings; struct list_head siblings;
Tag *tag; Tag tag;
/** /**
* The #Directory that contains this song. May be nullptr if * The #Directory that contains this song. May be nullptr if

View File

@ -149,7 +149,7 @@ SongFilter::Item::Match(const Song &song) const
return StringMatch(uri.c_str()); return StringMatch(uri.c_str());
} }
return song.tag != NULL && Match(*song.tag); return Match(song.tag);
} }
bool bool

View File

@ -74,8 +74,7 @@ song_print_info(Client &client, const Song &song)
if (song.mtime > 0) if (song.mtime > 0)
time_print(client, "Last-Modified", song.mtime); time_print(client, "Last-Modified", song.mtime);
if (song.tag != nullptr) tag_print(client, song.tag);
tag_print(client, *song.tag);
} }
void void

View File

@ -53,8 +53,7 @@ song_save(FILE *fp, const Song &song)
range_save(fp, song.start_ms, song.end_ms); range_save(fp, song.start_ms, song.end_ms);
if (song.tag != nullptr) tag_save(fp, song.tag);
tag_save(fp, *song.tag);
fprintf(fp, SONG_MTIME ": %li\n", (long)song.mtime); fprintf(fp, SONG_MTIME ": %li\n", (long)song.mtime);
fprintf(fp, SONG_END "\n"); fprintf(fp, SONG_END "\n");

View File

@ -30,14 +30,6 @@ extern "C" {
#include <stdlib.h> #include <stdlib.h>
static const char *
tag_get_value_checked(const Tag *tag, TagType type)
{
return tag != nullptr
? tag->GetValue(type)
: nullptr;
}
static int static int
compare_utf8_string(const char *a, const char *b) compare_utf8_string(const char *a, const char *b)
{ {
@ -55,11 +47,11 @@ compare_utf8_string(const char *a, const char *b)
* nullptr. * nullptr.
*/ */
static int static int
compare_string_tag_item(const Tag *a, const Tag *b, compare_string_tag_item(const Tag &a, const Tag &b,
TagType type) TagType type)
{ {
return compare_utf8_string(tag_get_value_checked(a, type), return compare_utf8_string(a.GetValue(type),
tag_get_value_checked(b, type)); b.GetValue(type));
} }
/** /**
@ -82,10 +74,10 @@ compare_number_string(const char *a, const char *b)
} }
static int static int
compare_tag_item(const Tag *a, const Tag *b, TagType type) compare_tag_item(const Tag &a, const Tag &b, TagType type)
{ {
return compare_number_string(tag_get_value_checked(a, type), return compare_number_string(a.GetValue(type),
tag_get_value_checked(b, type)); b.GetValue(type));
} }
/* Only used for sorting/searchin a songvec, not general purpose compares */ /* Only used for sorting/searchin a songvec, not general purpose compares */

View File

@ -98,8 +98,7 @@ Song::UpdateFile()
mtime = st.st_mtime; mtime = st.st_mtime;
delete tag; tag_builder.Commit(tag);
tag = tag_builder.CommitNew();
return true; return true;
} }
@ -123,8 +122,7 @@ Song::UpdateFileInArchive()
if (!tag_stream_scan(path_fs.c_str(), full_tag_handler, &tag_builder)) if (!tag_stream_scan(path_fs.c_str(), full_tag_handler, &tag_builder))
return false; return false;
delete tag; tag_builder.Commit(tag);
tag = tag_builder.CommitNew();
return true; return true;
} }

View File

@ -113,10 +113,7 @@ update_container_file(Directory &directory,
plugin.ScanFile(child_path_fs.c_str(), plugin.ScanFile(child_path_fs.c_str(),
add_tag_handler, &tag_builder); add_tag_handler, &tag_builder);
if (tag_builder.IsDefined()) tag_builder.Commit(song->tag);
song->tag = tag_builder.CommitNew();
else
tag_builder.Clear();
db_lock(); db_lock();
contdir->AddSong(song); contdir->AddSong(song);

View File

@ -524,7 +524,7 @@ Convert(const struct mpd_song *song)
for (const auto *i = &tag_table[0]; i->d != TAG_NUM_OF_ITEM_TYPES; ++i) for (const auto *i = &tag_table[0]; i->d != TAG_NUM_OF_ITEM_TYPES; ++i)
Copy(tag, i->d, song, i->s); Copy(tag, i->d, song, i->s);
s->tag = tag.CommitNew(); tag.Commit(s->tag);
return s; return s;
} }

View File

@ -205,7 +205,7 @@ upnpItemToSong(UPnPDirObject &&dirent, const char *uri)
uri = dirent.url.c_str(); uri = dirent.url.c_str();
Song *s = Song::NewFile(uri, nullptr); Song *s = Song::NewFile(uri, nullptr);
s->tag = new Tag(std::move(dirent.tag)); s->tag = std::move(dirent.tag);
return s; return s;
} }