From 565afefc66b7753ed27f6b7febaf32667c38c44a Mon Sep 17 00:00:00 2001 From: Max Kellermann Date: Sun, 15 Mar 2009 02:29:12 +0100 Subject: page: new library for reference counted buffers --- Makefile.am | 2 ++ src/page.c | 77 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/page.h | 85 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 164 insertions(+) create mode 100644 src/page.c create mode 100644 src/page.h diff --git a/Makefile.am b/Makefile.am index a76bd5b7f..f585ca62e 100644 --- a/Makefile.am +++ b/Makefile.am @@ -94,6 +94,7 @@ mpd_headers = \ src/chunk.h \ src/path.h \ src/mapper.h \ + src/page.h \ src/pcm_buffer.h \ src/pcm_utils.h \ src/pcm_convert.h \ @@ -194,6 +195,7 @@ src_mpd_SOURCES = \ src/chunk.c \ src/path.c \ src/mapper.c \ + src/page.c \ src/pcm_convert.c \ src/pcm_volume.c \ src/pcm_mix.c \ diff --git a/src/page.c b/src/page.c new file mode 100644 index 000000000..a4f52ae4a --- /dev/null +++ b/src/page.c @@ -0,0 +1,77 @@ +/* + * Copyright (C) 2003-2009 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 "page.h" + +#include + +#include +#include + +/** + * 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; +} + +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 new file mode 100644 index 000000000..6bee4996f --- /dev/null +++ b/src/page.h @@ -0,0 +1,85 @@ +/* + * Copyright (C) 2003-2009 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 +#include + +/** + * 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)]; +}; + +/** + * 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); + +/** + * 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); + +#endif -- cgit v1.2.3