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