1 /*
2  * Copyright (c) 2020-2021 Huawei Device Co., Ltd.
3  *
4  * HDF is dual licensed: you can use it either under the terms of
5  * the GPL, or the BSD license, at your option.
6  * See the LICENSE file in the root of this repository for complete details.
7  */
8 #ifndef SHARED_OBJ_H
9 #define SHARED_OBJ_H
10 
11 #include "osal_atomic.h"
12 #include "osal_mem.h"
13 
14 #define SHARED_OBJ(OBJ_TYPE) enum MessageEngineStatus status;                \
15     OsalAtomic refCount;                            \
16     struct OBJ_TYPE *(*Ref)(struct OBJ_TYPE * obj); \
17     void (*Disref)(struct OBJ_TYPE * obj);          \
18     void (*Destroy)(struct OBJ_TYPE * obj)
19 
20 #define DECLEAR_SHARED_OBJ_FUNC(OBJ_TYPE)                                                        \
21     struct OBJ_TYPE *Reference##OBJ_TYPE(struct OBJ_TYPE *obj);                                  \
22     void Disreference##OBJ_TYPE(struct OBJ_TYPE *obj);                                           \
23     ErrorCode InitSharedObj##OBJ_TYPE(struct OBJ_TYPE *obj, void (*Destroy)(struct OBJ_TYPE *)); \
24     void DeinitSharedObj##OBJ_TYPE(struct OBJ_TYPE *obj)
25 
26 #define IMPLEMENT_SHARED_OBJ(OBJ_TYPE)                                                          \
27     struct OBJ_TYPE *Reference##OBJ_TYPE(struct OBJ_TYPE *obj)                                  \
28     {                                                                                           \
29         if (obj == NULL) {                                                                      \
30             return NULL;                                                                        \
31         }                                                                                       \
32         if (obj->status > ME_STATUS_RUNNING) {                                                  \
33             return NULL;                                                                        \
34         }                                                                                       \
35         struct OBJ_TYPE *result = NULL;                                                         \
36         if (obj->status <= ME_STATUS_RUNNING && OsalAtomicRead(&obj->refCount) < MAX_OBJ_REF_COUNT) {            \
37             OsalAtomicInc(&obj->refCount);                                                       \
38             result = obj;                                                                       \
39         }                                                                                       \
40         return result;                                                                          \
41     }                                                                                           \
42     void Disreference##OBJ_TYPE(struct OBJ_TYPE *obj)                                           \
43     {                                                                                           \
44         if (obj == NULL) {                                                                      \
45             return;                                                                             \
46         }                                                                                       \
47         OsalAtomicDec(&obj->refCount);                                                           \
48         if (OsalAtomicRead(&obj->refCount) <= 0) {                                               \
49             obj->status = ME_STATUS_TODESTROY;                                                  \
50             if (obj->Destroy != NULL) {                                                         \
51                 obj->Destroy(obj);                                                              \
52                 OsalMemFree(obj);                                                               \
53             }                                                                                   \
54         }                                                                                       \
55     }                                                                                           \
56     ErrorCode InitSharedObj##OBJ_TYPE(struct OBJ_TYPE *obj, void (*Destroy)(struct OBJ_TYPE *)) \
57     {                                                                                           \
58         if (Destroy == NULL) {                                                                  \
59             return ME_ERROR_NULL_PTR;                                                           \
60         }                                                                                       \
61         OsalAtomicSet(&obj->refCount, 1);                                                        \
62         obj->Ref = Reference##OBJ_TYPE;                                                         \
63         obj->Disref = Disreference##OBJ_TYPE;                                                   \
64         obj->Destroy = Destroy;                                                                 \
65         return ME_SUCCESS;                                                                      \
66     }                                                                                           \
67     void DeinitSharedObj##OBJ_TYPE(struct OBJ_TYPE *obj)                                        \
68     {                                                                                           \
69         if (obj != NULL) {                                                                      \
70             OsalAtomicSet(&obj->refCount, 0);                                                    \
71         }                                                                                       \
72     }
73 
74 #define INIT_SHARED_OBJ(OBJ_TYPE, obj, DestroyFunc) InitSharedObj##OBJ_TYPE(obj, DestroyFunc)
75 #define DEINIT_SHARED_OBJ(OBJ_TYPE, obj) DeinitSharedObj##OBJ_TYPE(obj)
76 
77 
78 #endif
79