diff options
Diffstat (limited to '')
-rw-r--r-- | Makefile.am | 5 | ||||
-rw-r--r-- | src/IcyMetaDataServer.cxx | 7 | ||||
-rw-r--r-- | src/IcyMetaDataServer.hxx | 4 | ||||
-rw-r--r-- | src/Page.cxx (renamed from src/page.c) | 65 | ||||
-rw-r--r-- | src/Page.hxx (renamed from src/page.h) | 96 | ||||
-rw-r--r-- | src/output/HttpdClient.cxx | 49 | ||||
-rw-r--r-- | src/output/HttpdClient.hxx | 16 | ||||
-rw-r--r-- | src/output/HttpdInternal.hxx | 8 | ||||
-rw-r--r-- | src/output/HttpdOutputPlugin.cxx | 22 |
9 files changed, 127 insertions, 145 deletions
diff --git a/Makefile.am b/Makefile.am index c14ff2ed8..e2977a438 100644 --- a/Makefile.am +++ b/Makefile.am @@ -92,7 +92,6 @@ mpd_headers = \ src/AudioCompress/config.h \ src/AudioCompress/compress.h \ src/open.h \ - src/page.h \ src/Playlist.hxx \ src/playlist_error.h \ src/poison.h \ @@ -218,7 +217,7 @@ src_mpd_SOURCES = \ src/MusicPipe.cxx src/MusicPipe.hxx \ src/MusicChunk.cxx src/MusicChunk.hxx \ src/Mapper.cxx src/Mapper.hxx \ - src/page.c \ + src/Page.cxx src/Page.hxx \ src/Partition.hxx \ src/Permission.cxx src/Permission.hxx \ src/PlayerThread.cxx src/PlayerThread.hxx \ @@ -1325,7 +1324,7 @@ test_run_output_SOURCES = test/run_output.cxx \ src/audio_parser.c \ src/timer.c src/clock.c \ src/Tag.cxx src/TagNames.c src/TagPool.cxx \ - src/page.c \ + src/Page.cxx \ src/SocketUtil.cxx \ src/resolver.c \ src/OutputInit.cxx src/OutputFinish.cxx src/OutputList.cxx \ diff --git a/src/IcyMetaDataServer.cxx b/src/IcyMetaDataServer.cxx index e7bd0acf4..b1d075582 100644 --- a/src/IcyMetaDataServer.cxx +++ b/src/IcyMetaDataServer.cxx @@ -19,7 +19,7 @@ #include "config.h" #include "IcyMetaDataServer.hxx" -#include "page.h" +#include "Page.hxx" #include "tag.h" #include <glib.h> @@ -86,14 +86,13 @@ icy_server_metadata_string(const char *stream_title, const char* stream_url) return icy_metadata; } -struct page* +Page * icy_server_metadata_page(const struct tag *tag, const enum tag_type *types) { const gchar *tag_items[TAG_NUM_OF_ITEM_TYPES]; gint last_item, item; guint position; gchar *icy_string; - struct page *icy_metadata; gchar stream_title[(1 + 255 - 28) * 16]; // Length + Metadata - // "StreamTitle='';StreamUrl='';" // = 4081 - 28 @@ -131,7 +130,7 @@ icy_server_metadata_page(const struct tag *tag, const enum tag_type *types) if (icy_string == NULL) return NULL; - icy_metadata = page_new_copy(icy_string, (icy_string[0] * 16) + 1); + Page *icy_metadata = Page::Copy(icy_string, (icy_string[0] * 16) + 1); g_free(icy_string); diff --git a/src/IcyMetaDataServer.hxx b/src/IcyMetaDataServer.hxx index 78f1be7db..b344c61f2 100644 --- a/src/IcyMetaDataServer.hxx +++ b/src/IcyMetaDataServer.hxx @@ -22,12 +22,14 @@ #include "tag.h" +class Page; + char* icy_server_metadata_header(const char *name, const char *genre, const char *url, const char *content_type, int metaint); -struct page* +Page * icy_server_metadata_page(const struct tag *tag, const enum tag_type *types); #endif diff --git a/src/page.c b/src/Page.cxx index e2e22791f..bf30376e4 100644 --- a/src/page.c +++ b/src/Page.cxx @@ -18,72 +18,53 @@ */ #include "config.h" -#include "page.h" +#include "Page.hxx" #include <glib.h> +#include <new> + #include <assert.h> #include <string.h> -/** - * Allocates a new #page object, without filling the data element. - */ -static struct page * -page_new(size_t size) +Page * +Page::Create(size_t size) { - struct page *page = g_malloc(sizeof(*page) + size - - sizeof(page->data)); - - assert(size > 0); - - page->ref = 1; - page->size = size; - return page; + void *p = g_malloc(sizeof(Page) + size - + sizeof(Page::data)); + return ::new(p) Page(size); } -struct page * -page_new_copy(const void *data, size_t size) +Page * +Page::Copy(const void *data, size_t size) { - struct page *page = page_new(size); - - assert(data != NULL); + assert(data != nullptr); + Page *page = Create(size); memcpy(page->data, data, size); return page; } -struct page * -page_new_concat(const struct page *a, const struct page *b) +Page * +Page::Concat(const Page &a, const Page &b) { - struct page *page = page_new(a->size + b->size); + Page *page = Create(a.size + b.size); - memcpy(page->data, a->data, a->size); - memcpy(page->data + a->size, b->data, b->size); + memcpy(page->data, a.data, a.size); + memcpy(page->data + a.size, b.data, b.size); return page; } -void -page_ref(struct page *page) -{ - g_atomic_int_inc(&page->ref); -} - -static void -page_free(struct page *page) -{ - assert(page->ref == 0); - - g_free(page); -} - bool -page_unref(struct page *page) +Page::Unref() { - bool unused = g_atomic_int_dec_and_test(&page->ref); + bool unused = ref.Decrement(); - if (unused) - page_free(page); + if (unused) { + this->Page::~Page(); + g_free(this); + } return unused; } diff --git a/src/page.h b/src/Page.hxx index 8629298cd..2bc9a6ac5 100644 --- a/src/page.h +++ b/src/Page.hxx @@ -22,81 +22,83 @@ * This is a library which manages reference counted buffers. */ -#ifndef MPD_PAGE_H -#define MPD_PAGE_H +#ifndef MPD_PAGE_HXX +#define MPD_PAGE_HXX + +#include "util/RefCount.hxx" + +#include <algorithm> #include <stddef.h> -#include <stdbool.h> /** * A dynamically allocated buffer which keeps track of its reference * count. This is useful for passing buffers around, when several * instances hold references to one buffer. */ -struct page { +class Page { /** * The number of references to this buffer. This library uses * atomic functions to access it, i.e. no locks are required. * As soon as this attribute reaches zero, the buffer is * freed. */ - int ref; + RefCount ref; +public: /** * The size of this buffer in bytes. */ - size_t size; + const size_t size; /** * Dynamic array containing the buffer data. */ unsigned char data[sizeof(long)]; -}; -#ifdef __cplusplus -extern "C" { -#endif +protected: + Page(size_t _size):size(_size) {} + ~Page() = default; -/** - * Creates a new #page object, and copies data from the specified - * buffer. It is initialized with a reference count of 1. - * - * @param data the source buffer - * @param size the size of the source buffer - * @return the new #page object - */ -struct page * -page_new_copy(const void *data, size_t size); + /** + * Allocates a new #Page object, without filling the data + * element. + */ + static Page *Create(size_t size); -/** - * Concatenates two pages to a new page. - * - * @param a the first page - * @param b the second page, which is appended - */ -struct page * -page_new_concat(const struct page *a, const struct page *b); +public: + /** + * Creates a new #page object, and copies data from the + * specified buffer. It is initialized with a reference count + * of 1. + * + * @param data the source buffer + * @param size the size of the source buffer + */ + static Page *Copy(const void *data, size_t size); -/** - * Increases the reference counter. - * - * @param page the #page object - */ -void -page_ref(struct page *page); + /** + * Concatenates two pages to a new page. + * + * @param a the first page + * @param b the second page, which is appended + */ + static Page *Concat(const Page &a, const Page &b); -/** - * Decreases the reference counter. If it reaches zero, the #page is - * freed. - * - * @param page the #page object - * @return true if the #page has been freed - */ -bool -page_unref(struct page *page); + /** + * Increases the reference counter. + */ + void Ref() { + ref.Increment(); + } -#ifdef __cplusplus -} -#endif + /** + * Decreases the reference counter. If it reaches zero, the #page is + * freed. + * + * @return true if the #page has been freed + */ + bool Unref(); +}; #endif diff --git a/src/output/HttpdClient.cxx b/src/output/HttpdClient.cxx index 5ac3bf7cc..dd2f44fa0 100644 --- a/src/output/HttpdClient.cxx +++ b/src/output/HttpdClient.cxx @@ -21,7 +21,7 @@ #include "HttpdClient.hxx" #include "HttpdInternal.hxx" #include "util/fifo_buffer.h" -#include "page.h" +#include "Page.hxx" #include "IcyMetaDataServer.hxx" #include "glib_socket.h" @@ -38,15 +38,15 @@ HttpdClient::~HttpdClient() g_source_remove(write_source_id); if (current_page != nullptr) - page_unref(current_page); + current_page->Unref(); for (auto page : pages) - page_unref(page); + page->Unref(); } else fifo_buffer_free(input); if (metadata) - page_unref(metadata); + metadata->Unref(); g_source_remove(read_source_id); g_io_channel_unref(channel); @@ -379,7 +379,7 @@ HttpdClient::CancelQueue() return; for (auto page : pages) - page_unref(page); + page->Unref(); pages.clear(); if (write_source_id != 0 && current_page == nullptr) { @@ -390,36 +390,34 @@ HttpdClient::CancelQueue() static GIOStatus write_page_to_channel(GIOChannel *channel, - const struct page *page, size_t position, + const Page &page, size_t position, gsize *bytes_written_r, GError **error) { assert(channel != nullptr); - assert(page != nullptr); - assert(position < page->size); + assert(position < page.size); return g_io_channel_write_chars(channel, - (const gchar*)page->data + position, - page->size - position, + (const gchar*)page.data + position, + page.size - position, bytes_written_r, error); } static GIOStatus -write_n_bytes_to_channel(GIOChannel *channel, const struct page *page, +write_n_bytes_to_channel(GIOChannel *channel, const Page &page, size_t position, gint n, gsize *bytes_written_r, GError **error) { GIOStatus status; assert(channel != nullptr); - assert(page != nullptr); - assert(position < page->size); + assert(position < page.size); if (n == -1) { status = write_page_to_channel (channel, page, position, bytes_written_r, error); } else { status = g_io_channel_write_chars(channel, - (const gchar*)page->data + position, + (const gchar*)page.data + position, n, bytes_written_r, error); } @@ -466,7 +464,7 @@ HttpdClient::Write() if (!metadata_sent) { status = write_page_to_channel(channel, - metadata, + *metadata, metadata_to_write, &bytes_written, &error); @@ -478,13 +476,12 @@ HttpdClient::Write() metadata_sent = true; } } else { - struct page *empty_meta; guchar empty_data = 0; - empty_meta = page_new_copy(&empty_data, 1); + Page *empty_meta = Page::Copy(&empty_data, 1); status = write_page_to_channel(channel, - empty_meta, + *empty_meta, metadata_to_write, &bytes_written, &error); @@ -494,11 +491,13 @@ HttpdClient::Write() metadata_fill = 0; metadata_current_position = 0; } + + empty_meta->Unref(); } bytes_written = 0; } else { - status = write_n_bytes_to_channel(channel, current_page, + status = write_n_bytes_to_channel(channel, *current_page, current_position, bytes_to_write, &bytes_written, &error); } @@ -512,7 +511,7 @@ HttpdClient::Write() metadata_fill += bytes_written; if (current_position >= current_page->size) { - page_unref(current_page); + current_page->Unref(); current_page = nullptr; if (pages.empty()) { @@ -561,13 +560,13 @@ httpd_client_out_event(gcc_unused GIOChannel *source, } void -HttpdClient::PushPage(struct page *page) +HttpdClient::PushPage(Page *page) { if (state != RESPONSE) /* the client is still writing the HTTP request */ return; - page_ref(page); + page->Ref(); pages.push_back(page); if (write_source_id == 0) @@ -577,16 +576,16 @@ HttpdClient::PushPage(struct page *page) } void -HttpdClient::PushMetaData(struct page *page) +HttpdClient::PushMetaData(Page *page) { if (metadata) { - page_unref(metadata); + metadata->Unref(); metadata = nullptr; } g_return_if_fail (page); - page_ref(page); + page->Ref(); metadata = page; metadata_sent = false; } diff --git a/src/output/HttpdClient.hxx b/src/output/HttpdClient.hxx index 8fb7c8b28..1dd4eead1 100644 --- a/src/output/HttpdClient.hxx +++ b/src/output/HttpdClient.hxx @@ -29,7 +29,7 @@ #include <stddef.h> struct HttpdOutput; -struct page; +class Page; class HttpdClient final { /** @@ -76,14 +76,14 @@ class HttpdClient final { } state; /** - * A queue of #page objects to be sent to the client. + * A queue of #Page objects to be sent to the client. */ - std::list<page *> pages; + std::list<Page *> pages; /** * The #page which is currently being sent to the client. */ - page *current_page; + Page *current_page; /** * The amount of bytes which were already sent from @@ -120,9 +120,9 @@ class HttpdClient final { guint metaint; /** - * The metadata as #page which is currently being sent to the client. + * The metadata as #Page which is currently being sent to the client. */ - page *metadata; + Page *metadata; /* * The amount of bytes which were already sent from the metadata. @@ -204,12 +204,12 @@ public: /** * Appends a page to the client's queue. */ - void PushPage(page *page); + void PushPage(Page *page); /** * Sends the passed metadata. */ - void PushMetaData(page *page); +void PushMetaData(Page *page); }; #endif diff --git a/src/output/HttpdInternal.hxx b/src/output/HttpdInternal.hxx index 1c2fdfb16..702f4ad3d 100644 --- a/src/output/HttpdInternal.hxx +++ b/src/output/HttpdInternal.hxx @@ -85,12 +85,12 @@ struct HttpdOutput { /** * The header page, which is sent to every client on connect. */ - struct page *header; + Page *header; /** * The metadata, which is sent to every client. */ - struct page *metadata; + Page *metadata; /** * The configured name. @@ -178,14 +178,14 @@ struct HttpdOutput { * Reads data from the encoder (as much as available) and * returns it as a new #page object. */ - page *ReadPage(); + Page *ReadPage(); /** * Broadcasts a page struct to all clients. * * Mutext must not be locked. */ - void BroadcastPage(struct page *page); + void BroadcastPage(Page *page); /** * Broadcasts data from the encoder to all clients. diff --git a/src/output/HttpdOutputPlugin.cxx b/src/output/HttpdOutputPlugin.cxx index 52b2e0e8d..a9b27c483 100644 --- a/src/output/HttpdOutputPlugin.cxx +++ b/src/output/HttpdOutputPlugin.cxx @@ -25,7 +25,7 @@ #include "encoder_plugin.h" #include "encoder_list.h" #include "resolver.h" -#include "page.h" +#include "Page.hxx" #include "IcyMetaDataServer.hxx" #include "fd_util.h" #include "ServerSocket.hxx" @@ -156,7 +156,7 @@ httpd_output_finish(struct audio_output *ao) HttpdOutput *httpd = (HttpdOutput *)ao; if (httpd->metadata) - page_unref(httpd->metadata); + httpd->metadata->Unref(); encoder_finish(httpd->encoder); server_socket_free(httpd->server_socket); @@ -230,7 +230,7 @@ httpd_listen_in_event(int fd, const struct sockaddr *address, } } -struct page * +Page * HttpdOutput::ReadPage() { if (unflushed_input >= 65536) { @@ -257,7 +257,7 @@ HttpdOutput::ReadPage() if (size == 0) return NULL; - return page_new_copy(buffer, size); + return Page::Copy(buffer, size); } static bool @@ -337,7 +337,7 @@ HttpdOutput::Close() clients.clear(); if (header != NULL) - page_unref(header); + header->Unref(); encoder_close(encoder); } @@ -398,7 +398,7 @@ httpd_output_delay(struct audio_output *ao) } void -HttpdOutput::BroadcastPage(struct page *page) +HttpdOutput::BroadcastPage(Page *page) { assert(page != NULL); @@ -419,10 +419,10 @@ HttpdOutput::BroadcastFromEncoder() } mutex.unlock(); - struct page *page; + Page *page; while ((page = ReadPage()) != nullptr) { BroadcastPage(page); - page_unref(page); + page->Unref(); } } @@ -492,10 +492,10 @@ HttpdOutput::SendTag(const struct tag *tag) used as the new "header" page, which is sent to all new clients */ - struct page *page = ReadPage(); + Page *page = ReadPage(); if (page != NULL) { if (header != NULL) - page_unref(header); + header->Unref(); header = page; BroadcastPage(page); } @@ -503,7 +503,7 @@ HttpdOutput::SendTag(const struct tag *tag) /* use Icy-Metadata */ if (metadata != NULL) - page_unref(metadata); + metadata->Unref(); static constexpr tag_type types[] = { TAG_ALBUM, TAG_ARTIST, TAG_TITLE, |