1 /* 2 * Copyright (c) 2006-2023, RT-Thread Development Team 3 * 4 * SPDX-License-Identifier: Apache-2.0 5 * 6 * Change Logs: 7 * Date Author Notes 8 * 2022-3-1 zhouxiaohu first version 9 * 2023-5-18 GuEe-GUI implemented by rtatomic 10 */ 11 12 #ifndef __UTIL_REF_H__ 13 #define __UTIL_REF_H__ 14 15 #include <rtatomic.h> 16 17 /** 18 * struct ref must be embedded in an object. 19 * it acts as a reference counter for the object. 20 */ 21 struct rt_ref 22 { 23 rt_atomic_t refcount; 24 }; 25 26 #define RT_REF_INIT(n) { .refcount = n, } 27 rt_ref_init(struct rt_ref * r)28rt_inline void rt_ref_init(struct rt_ref *r) 29 { 30 rt_atomic_store(&r->refcount, 1); 31 } 32 rt_ref_read(struct rt_ref * r)33rt_inline unsigned int rt_ref_read(struct rt_ref *r) 34 { 35 return rt_atomic_load(&r->refcount); 36 } 37 38 /** 39 * ref_get 40 * increment reference counter for object. 41 */ rt_ref_get(struct rt_ref * r)42rt_inline void rt_ref_get(struct rt_ref *r) 43 { 44 rt_atomic_add(&r->refcount, 1); 45 } 46 47 /** 48 * ref_put 49 * decrement reference counter for object. 50 * If the reference counter is zero, call release(). 51 * 52 * Return 1 means the object's reference counter is zero and release() is called. 53 */ rt_ref_put(struct rt_ref * r,void (* release)(struct rt_ref * r))54rt_inline int rt_ref_put(struct rt_ref *r, void (*release)(struct rt_ref *r)) 55 { 56 if (rt_atomic_dec_and_test(&r->refcount)) 57 { 58 release(r); 59 60 return 1; 61 } 62 63 return 0; 64 } 65 66 /** 67 * ref_get_unless_zero - Increment refcount for object unless it is zero. 68 * Return non-zero if the increment succeeded. Otherwise return 0. 69 */ rt_ref_get_unless_zero(struct rt_ref * r)70rt_inline int rt_ref_get_unless_zero(struct rt_ref *r) 71 { 72 return (int)rt_atomic_inc_not_zero(&r->refcount); 73 } 74 75 #endif /* __UTIL_REF_H__ */ 76