From patchwork Sat Jun 27 15:16:44 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Nicolas George X-Patchwork-Id: 20647 Return-Path: X-Original-To: patchwork@ffaux-bg.ffmpeg.org Delivered-To: patchwork@ffaux-bg.ffmpeg.org Received: from ffbox0-bg.mplayerhq.hu (ffbox0-bg.ffmpeg.org [79.124.17.100]) by ffaux.localdomain (Postfix) with ESMTP id 7AA3344B923 for ; Sat, 27 Jun 2020 18:16:56 +0300 (EEST) Received: from [127.0.1.1] (localhost [127.0.0.1]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id 596DA68B66A; Sat, 27 Jun 2020 18:16:56 +0300 (EEST) X-Original-To: ffmpeg-devel@ffmpeg.org Delivered-To: ffmpeg-devel@ffmpeg.org Received: from nef.ens.fr (nef2.ens.fr [129.199.96.40]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTPS id 4F23768B656 for ; Sat, 27 Jun 2020 18:16:49 +0300 (EEST) X-ENS-nef-client: 129.199.129.80 Received: from phare.normalesup.org (phare.normalesup.org [129.199.129.80]) by nef.ens.fr (8.14.4/1.01.28121999) with ESMTP id 05RFGmTe018913 for ; Sat, 27 Jun 2020 17:16:48 +0200 Received: by phare.normalesup.org (Postfix, from userid 1001) id 4CC6FE6C30; Sat, 27 Jun 2020 17:16:48 +0200 (CEST) From: Nicolas George To: ffmpeg-devel@ffmpeg.org Date: Sat, 27 Jun 2020 17:16:44 +0200 Message-Id: <20200627151646.2593306-1-george@nsup.org> X-Mailer: git-send-email 2.27.0 MIME-Version: 1.0 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.4.3 (nef.ens.fr [129.199.96.32]); Sat, 27 Jun 2020 17:16:48 +0200 (CEST) Subject: [FFmpeg-devel] [PATCH 1/3] lavu: add a template for refcounted objects. X-BeenThere: ffmpeg-devel@ffmpeg.org X-Mailman-Version: 2.1.20 Precedence: list List-Id: FFmpeg development discussions and patches List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Reply-To: FFmpeg development discussions and patches Errors-To: ffmpeg-devel-bounces@ffmpeg.org Sender: "ffmpeg-devel" Signed-off-by: Nicolas George --- libavutil/avrefcount_template.h | 140 ++++++++++++++++++++++++++++++++ tests/ref/fate/source | 1 + 2 files changed, 141 insertions(+) create mode 100644 libavutil/avrefcount_template.h I will need to refcount something soon. Recently, the need to stop abusing AVBuffer for all refcounting was mentioned on the list. So here is an attempt at isolating the refcounting itself. This is not the final verion, I will first work on the "something" to make sure it suits the needs. But it is a first version. Anton, I would appreciate if you had a look at this and told me if there is something you strongly dislike about before I have piled too much efforts over it. diff --git a/libavutil/avrefcount_template.h b/libavutil/avrefcount_template.h new file mode 100644 index 0000000000..8d0a37370c --- /dev/null +++ b/libavutil/avrefcount_template.h @@ -0,0 +1,140 @@ +/* + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** + * Create a set of functions to implement lockless thread-safe reference + * counting for a structure type. + * + * To use this template, you must first define a few macros to describe the + * type and select the name of the functions and their properties. Then you + * include this template as a header file. And finally you use the functions + * that it provides. + * + * Before including this header, you must define the following macros: + * + * AVRC_TYPE the name of the type that will be refcounted. + * Example: #define AVRC_TYPE AVBuffer + * + * AVRC_PREFIX the prefix for all the related functions. + * Example: #define AVRC_PREFIX ff_buffer_ + * + * AVRC_FIELD the field in AVRC_TYPE holding the reference count, + * must be atomic_uint as defined in stdatomic.h. + * + * You can define the following macros, otherwise sane defaults are used: + * + * AVRC_SCOPE the scope for the defined functions, + * defaults to static inline. + * Example: #define AVRC_SCOPE static + * + * AVRC_INIT_REF_COUNT the initial reference count, defaults to 1. + * + * AVRC_FREE the function or macro to call when the reference count drops + * to 0, defaults to AVRC_PREFIX_free(). + * + * After the template has been included, the following functions will be + * defined, with the appropriate prefix: + * + * void PREFIX_init(TYPE *rc); + * + * Init the reference count field of a structure, to be used in functions + * creating new instances. + * + * TYPE *PREFIX_ref(TYPE *rc); + * + * Increase the reference count by one. Returns rc itself for convenience. + * + * void PREFIX_unrefp(TYPE **rc); + * + * Decrease the reference count by one and set *rc to NULL. + * If the reference count drops to 0, call AVRC_FREE(). + * + * unsigned PREFIX_get_ref_count(TYPE *rc); + * + * Return the current number of references. + * + */ + +#include + +#ifndef AVRC_TYPE +#error AVRC_TYPE must be defined. +#endif + +#ifndef AVRC_PREFIX +#error AVRC_PREFIX must be defined. +#endif + +#ifndef AVRC_FIELD +#error AVRC_FIELD must be defined. +#endif + +#ifndef AVRC_SCOPE +#define AVRC_SCOPE static inline +#endif + +#ifndef AVRC_INIT_REF_COUNT +#define AVRC_INIT_REF_COUNT 1 +#endif + +#ifndef AVRC_FREE +#define AVRC_FREE FFRC_PREFIXED(free) +#endif + +#define FFRC_CALL(macro, args) macro args +#define FFRC_CONCAT(prefix, suffix) prefix##suffix +#define FFRC_PREFIXED(suffix) FFRC_CALL(FFRC_CONCAT, (AVRC_PREFIX, suffix)) + +AVRC_SCOPE void +FFRC_PREFIXED(init_ref_count)(AVRC_TYPE *rc) +{ + atomic_init(&rc->AVRC_FIELD, AVRC_INIT_REF_COUNT); +} + +AVRC_SCOPE AVRC_TYPE * +FFRC_PREFIXED(ref)(AVRC_TYPE *rc) +{ + atomic_fetch_add_explicit(&rc->AVRC_FIELD, 1, memory_order_relaxed); + return rc; +} + +AVRC_SCOPE void +FFRC_PREFIXED(unrefp)(AVRC_TYPE **rc) +{ + if (atomic_fetch_sub_explicit(&(*rc)->AVRC_FIELD, 1, memory_order_acq_rel) == 1) { + AVRC_FREE(*rc); + *rc = NULL; + } +} + +AVRC_SCOPE unsigned +FFRC_PREFIXED(get_ref_count)(AVRC_TYPE *rc) +{ + return atomic_load(&rc->AVRC_FIELD); +} + +#undef FFRC_CALL +#undef FFRC_CONCAT +#undef FFRC_PREFIXED + +#undef AVRC_TYPE +#undef AVRC_PREFIX +#undef AVRC_FIELD +#undef AVRC_SCOPE +#undef AVRC_INIT_REF_COUNT +#undef AVRC_FREE diff --git a/tests/ref/fate/source b/tests/ref/fate/source index c64bc05241..32954fd828 100644 --- a/tests/ref/fate/source +++ b/tests/ref/fate/source @@ -20,5 +20,6 @@ Headers without standard inclusion guards: compat/djgpp/math.h compat/float/float.h compat/float/limits.h +libavutil/avrefcount_template.h Use of av_clip() where av_clip_uintp2() could be used: Use of av_clip() where av_clip_intp2() could be used: