From fe3f0332f71258354b70e5db685b56934f0df703 Mon Sep 17 00:00:00 2001
From: Max Kellermann <max@duempel.org>
Date: Wed, 30 Jan 2013 09:18:52 +0100
Subject: page: convert to C++

---
 Makefile.am                      |   5 +-
 src/IcyMetaDataServer.cxx        |   7 ++-
 src/IcyMetaDataServer.hxx        |   4 +-
 src/Page.cxx                     |  70 ++++++++++++++++++++++++++
 src/Page.hxx                     | 104 +++++++++++++++++++++++++++++++++++++++
 src/output/HttpdClient.cxx       |  49 +++++++++---------
 src/output/HttpdClient.hxx       |  16 +++---
 src/output/HttpdInternal.hxx     |   8 +--
 src/output/HttpdOutputPlugin.cxx |  22 ++++-----
 src/page.c                       |  89 ---------------------------------
 src/page.h                       | 102 --------------------------------------
 11 files changed, 229 insertions(+), 247 deletions(-)
 create mode 100644 src/Page.cxx
 create mode 100644 src/Page.hxx
 delete mode 100644 src/page.c
 delete mode 100644 src/page.h

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.cxx b/src/Page.cxx
new file mode 100644
index 000000000..bf30376e4
--- /dev/null
+++ b/src/Page.cxx
@@ -0,0 +1,70 @@
+/*
+ * Copyright (C) 2003-2011 The Music Player Daemon Project
+ * http://www.musicpd.org
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include "config.h"
+#include "Page.hxx"
+
+#include <glib.h>
+
+#include <new>
+
+#include <assert.h>
+#include <string.h>
+
+Page *
+Page::Create(size_t size)
+{
+	void *p = g_malloc(sizeof(Page) + size -
+			   sizeof(Page::data));
+	return ::new(p) Page(size);
+}
+
+Page *
+Page::Copy(const void *data, size_t size)
+{
+	assert(data != nullptr);
+
+	Page *page = Create(size);
+	memcpy(page->data, data, size);
+	return page;
+}
+
+Page *
+Page::Concat(const Page &a, const Page &b)
+{
+	Page *page = Create(a.size + b.size);
+
+	memcpy(page->data, a.data, a.size);
+	memcpy(page->data + a.size, b.data, b.size);
+
+	return page;
+}
+
+bool
+Page::Unref()
+{
+	bool unused = ref.Decrement();
+
+	if (unused) {
+		this->Page::~Page();
+		g_free(this);
+	}
+
+	return unused;
+}
diff --git a/src/Page.hxx b/src/Page.hxx
new file mode 100644
index 000000000..2bc9a6ac5
--- /dev/null
+++ b/src/Page.hxx
@@ -0,0 +1,104 @@
+/*
+ * Copyright (C) 2003-2011 The Music Player Daemon Project
+ * http://www.musicpd.org
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+/** \file
+ *
+ * This is a library which manages reference counted buffers.
+ */
+
+#ifndef MPD_PAGE_HXX
+#define MPD_PAGE_HXX
+
+#include "util/RefCount.hxx"
+
+#include <algorithm>
+
+#include <stddef.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.
+ */
+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.
+	 */
+	RefCount ref;
+
+public:
+	/**
+	 * The size of this buffer in bytes.
+	 */
+	const size_t size;
+
+	/**
+	 * Dynamic array containing the buffer data.
+	 */
+	unsigned char data[sizeof(long)];
+
+protected:
+	Page(size_t _size):size(_size) {}
+	~Page() = default;
+
+	/**
+	 * Allocates a new #Page object, without filling the data
+	 * element.
+	 */
+	static Page *Create(size_t size);
+
+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);
+
+	/**
+	 * 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);
+
+	/**
+	 * Increases the reference counter.
+	 */
+	void Ref() {
+		ref.Increment();
+	}
+
+	/**
+	 * 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,
diff --git a/src/page.c b/src/page.c
deleted file mode 100644
index e2e22791f..000000000
--- a/src/page.c
+++ /dev/null
@@ -1,89 +0,0 @@
-/*
- * Copyright (C) 2003-2011 The Music Player Daemon Project
- * http://www.musicpd.org
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-
-#include "config.h"
-#include "page.h"
-
-#include <glib.h>
-
-#include <assert.h>
-#include <string.h>
-
-/**
- * Allocates a new #page object, without filling the data element.
- */
-static struct page *
-page_new(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;
-}
-
-struct page *
-page_new_copy(const void *data, size_t size)
-{
-	struct page *page = page_new(size);
-
-	assert(data != NULL);
-
-	memcpy(page->data, data, size);
-	return page;
-}
-
-struct page *
-page_new_concat(const struct page *a, const struct page *b)
-{
-	struct page *page = page_new(a->size + 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)
-{
-	bool unused = g_atomic_int_dec_and_test(&page->ref);
-
-	if (unused)
-		page_free(page);
-
-	return unused;
-}
diff --git a/src/page.h b/src/page.h
deleted file mode 100644
index 8629298cd..000000000
--- a/src/page.h
+++ /dev/null
@@ -1,102 +0,0 @@
-/*
- * Copyright (C) 2003-2011 The Music Player Daemon Project
- * http://www.musicpd.org
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-
-/** \file
- *
- * This is a library which manages reference counted buffers.
- */
-
-#ifndef MPD_PAGE_H
-#define MPD_PAGE_H
-
-#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 {
-	/**
-	 * 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;
-
-	/**
-	 * The size of this buffer in bytes.
-	 */
-	size_t size;
-
-	/**
-	 * Dynamic array containing the buffer data.
-	 */
-	unsigned char data[sizeof(long)];
-};
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/**
- * 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);
-
-/**
- * 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);
-
-/**
- * Increases the reference counter.
- *
- * @param page the #page object
- */
-void
-page_ref(struct page *page);
-
-/**
- * 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);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif
-- 
cgit v1.2.3