1 /*!
2  * \file        sccp_refcount.h
3  * \brief       SCCP RefCount Header
4  * \note        This program is free software and may be modified and distributed under the terms of the GNU Public License.
5  *              See the LICENSE file at the top of the source tree.
6  */
7 #pragma once
8 
9 #include "sccp_cli.h"
10 
11 /* forward declarations */
12 struct mansession;
13 struct message;
14 
15 __BEGIN_C_EXTERN__
16 #define REFCOUNT_INDENTIFIER_SIZE 32
17 enum sccp_refcounted_types {
18 	SCCP_REF_PARTICIPANT = 1,
19 	SCCP_REF_CONFERENCE,
20 	SCCP_REF_EVENT,
21 	SCCP_REF_CHANNEL,
22 	SCCP_REF_LINEDEVICE,
23 	SCCP_REF_LINE,
24 	SCCP_REF_DEVICE,
25 #if CS_TEST_FRAMEWORK
26 	SCCP_REF_TEST,
27 #endif
28 };
29 
30 enum sccp_refcount_runstate {
31 	SCCP_REF_RUNNING = 1,
32 	SCCP_REF_STOPPED = 0,
33 	SCCP_REF_DESTROYED = -1
34 };
35 
36 //#if !defined(CS_ASTOBJ_REFCOUNT)
37 //#endif
38 
39 SCCP_API void SCCP_CALL sccp_refcount_init(void);
40 SCCP_API void SCCP_CALL sccp_refcount_destroy(void);
41 SCCP_API int __PURE__ SCCP_CALL sccp_refcount_isRunning(void);
42 SCCP_API void * SCCP_CALL  const sccp_refcount_object_alloc(size_t size, enum sccp_refcounted_types type, const char *identifier, int (*destructor)(const void *));
43 SCCP_API void SCCP_CALL sccp_refcount_updateIdentifier(const void * const ptr, const char * const identifier);
44 SCCP_API void * SCCP_CALL  const sccp_refcount_retain(const void * const ptr, const char *filename, int lineno, const char *func);
45 SCCP_API void * SCCP_CALL  const sccp_refcount_release(const void * * const ptr, const char *filename, int lineno, const char *func);
46 SCCP_API void SCCP_CALL sccp_refcount_replace(const void * * const replaceptr, const void *const newptr, const char *filename, int lineno, const char *func);
47 SCCP_API int SCCP_CALL sccp_show_refcount(int fd, sccp_cli_totals_t *totals, struct mansession *s, const struct message *m, int argc, char *argv[]);
48 SCCP_API void SCCP_CALL sccp_refcount_autorelease(void *ptr);
49 #if CS_REFCOUNT_DEBUG
50 struct ast_str;
51 #define pbx_str_t struct ast_str
52 SCCP_API void SCCP_CALL sccp_refcount_addRelationship(const void * const parentWeakPtr, const void * const childPtr);
53 SCCP_API void SCCP_CALL sccp_refcount_removeRelationship(const void * const parentWeakPtr, const void * const childPtr);
54 SCCP_API void SCCP_CALL sccp_refcount_gen_report(const void * const ptr, pbx_str_t **buf);
55 #endif
56 #ifdef CS_EXPERIMENTAL
57 SCCP_API int SCCP_CALL sccp_refcount_force_release(long findobj, char *identifier);
58 #endif
59 
60 typedef struct {
61 	const void ** const ptr;
62 	const char *file;
63 	const char *func;
64 	int line;
65 } auto_ref_t;
66 
67 #define __AUTO_RELEASE2(_type, _var, _initial, _file, _func, _line, _counter) 									\
68 	_type * _var = (_initial);                                          									\
69 	auto_ref_t __attribute__((cleanup(sccp_refcount_autorelease), unused)) ref##_counter = { (const void ** const) & (_var), _file, _func, _line };
70 #	define __AUTO_RELEASE1(_type, _var, _initial, _file, _func, _line, _counter) __AUTO_RELEASE2(_type, _var, _initial, _file, _func, _line, _counter)
71 #	define AUTO_RELEASE(_type, _var, _initial)                                 __AUTO_RELEASE1(_type, _var, _initial, __FILE__, __PRETTY_FUNCTION__, __LINE__, __COUNTER__)
72 
73 
74 #define sccp_refcount_retain_type(_type, _x) 		({											\
75 	pbx_assert(PTR_TYPE_CMP(const _type *const, (_x) ) == 1); 										\
76 	(_type *)sccp_refcount_retain((_x), __FILE__, __LINE__, __PRETTY_FUNCTION__);								\
77 })
78 #define sccp_refcount_release_type(_type,_x)		({											\
79 	pbx_assert(PTR_TYPE_CMP(_type * *const, (_x) ) == 1);		 									\
80 	sccp_refcount_release((const void ** const)(_x), __FILE__, __LINE__, __PRETTY_FUNCTION__);						\
81 })
82 #define sccp_refcount_refreplace_type(_type,_x, _y) 	({											\
83 	pbx_assert(PTR_TYPE_CMP(_type * *const, (_x)) == 1 && PTR_TYPE_CMP(const _type *const, (_y)) == 1);					\
84 	sccp_refcount_replace((const void ** const)(_x), (_y), __FILE__, __LINE__, __PRETTY_FUNCTION__);					\
85 })
86 
87 __END_C_EXTERN__
88 
89 #if 0 /* UNUSED */
90 /* *INDENT-OFF* */
91 /* Automatically Retain/Release */
92 #define __GET_WITH_REF1(_dst,_src,_file,_line,_func) 												\
93         _dst = _src;																\
94         int with_counter_##_line=4;														\
95         while (with_counter_##_line-- > 0)													\
96                 if (3 == with_counter_##_line) {		/* ENTRY */									\
97                         if (!_dst || !(_dst = sccp_refcount_retain(_dst,_file,_line,_func))) {							\
98                                 pbx_log(LOG_NOTICE, "[%s:%d] %s: Failed to retain (%p)\n",  _file,_line,_func,_src);				\
99                                 with_counter_##_line=0;												\
100                                 break;														\
101                         } else { pbx_log(LOG_NOTICE, "retain  %p, %d, %d\n", _src, _line, with_counter_##_line); }				\
102                 } else																\
103                 if (1 == with_counter_##_line) {		/* EXIT */									\
104                         if ((_dst = sccp_refcount_release(_dst,_file,_line,_func)) != NULL) {							\
105                                 pbx_log(LOG_NOTICE, "[%s:%d] %s: Failed to release (%p)\n", _file,_line,_func,_src);				\
106                         } else { pbx_log(LOG_NOTICE, "release %p, %d, %d\n", _src, _line, with_counter_##_line); }				\
107                         break;															\
108                 } else          				/* DO INBETWEEN*/
109 
110 #define __GET_WITH_REF(_dst,_src,_file,_line,_func) __GET_WITH_REF1(_dst,_src,_file,_line,_func)
111 #define GETWITHREF(_dst,_src) __GET_WITH_REF(_dst,_src,__FILE__,__LINE__,__PRETTY_FUNCTION__)
112 
113 /* Call with_get_ref after creating unique local variable to use during retain/release */
114 #define __TOKENPASTE(x, y) x ## y
115 #define __TOKENPASTE2(x, y) __TOKENPASTE(x, y)
116 #define __WITH_REF(_src,_file,_line,_func) 													\
117         typeof(_src) __TOKENPASTE(sccp_with_ref_,_line);											\
118         __GET_WITH_REF(__TOKENPASTE(sccp_with_ref_,_line),_src,_file,_line,_func)
119 #define WITHREF(_src) __WITH_REF(_src,__FILE__,__LINE__,__PRETTY_FUNCTION__)
120 /* *INDENT-ON* */
121 
122 
123 /* example use */
124 #if 0
125 	sccp_device_t *d = NULL;
126 	WITHREF(channel) {
127 		GETWITHREF(d, channel->privateData->device) {
128 			channel->privateData->microphone = enabled;
129 			pbx_log(LOG_NOTICE, "Within retain section\n");
130 			if (enabled) {
131 				channel->isMicrophoneEnabled = sccp_always_true;
132 				if ((channel->rtp.audio.mediaTransmissionState & SCCP_RTP_STATUS_ACTIVE)) {
133 					sccp_dev_set_microphone(d, SKINNY_STATIONMIC_ON);
134 				}
135 			} else {
136 				channel->isMicrophoneEnabled = sccp_always_false;
137 				if ((channel->rtp.audio.mediaTransmissionState & SCCP_RTP_STATUS_ACTIVE)) {
138 					sccp_dev_set_microphone(d, SKINNY_STATIONMIC_OFF);
139 				}
140 			}
141 		}
142 	}
143 #endif // unused
144 
145 #endif // unused
146 // kate: indent-width 8; replace-tabs off; indent-mode cstyle; auto-insert-doxygen on; line-numbers on; tab-indents on; keep-extra-spaces off; auto-brackets off
147