Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Menu
Open sidebar
BC
public
liblinphone
Commits
fcbce751
Commit
fcbce751
authored
Nov 06, 2017
by
Ronan
Browse files
feat(c-wrapper): deal with floating references
parent
a77a4f85
Changes
2
Hide whitespace changes
Inline
Side-by-side
src/c-wrapper/internal/c-tools.h
View file @
fcbce751
...
...
@@ -121,10 +121,19 @@ private:
// Wrapped Objects.
// ---------------------------------------------------------------------------
enum
class
WrappedObjectOwner
:
int
{
Internal
,
External
};
template
<
typename
CppType
>
struct
WrappedBaseObject
{
belle_sip_object_t
base
;
std
::
shared_ptr
<
CppType
>
cppPtr
;
std
::
weak_ptr
<
CppType
>
weakCppPtr
;
// By default: Internal.
WrappedObjectOwner
owner
;
};
template
<
typename
CppType
>
...
...
@@ -143,6 +152,23 @@ private:
}
public:
// ---------------------------------------------------------------------------
// Belle sip handlers.
// Deal with floating references.
// ---------------------------------------------------------------------------
static
void
onBelleSipFirstRef
(
belle_sip_object_t
*
base
)
{
WrappedBaseObject
<
BaseObject
>
*
wrappedObject
=
reinterpret_cast
<
WrappedBaseObject
<
BaseObject
>
*>
(
base
);
if
(
wrappedObject
->
owner
==
WrappedObjectOwner
::
Internal
)
wrappedObject
->
cppPtr
=
wrappedObject
->
weakCppPtr
.
lock
();
}
static
void
onBelleSipLastRef
(
belle_sip_object_t
*
base
)
{
WrappedBaseObject
<
BaseObject
>
*
wrappedObject
=
reinterpret_cast
<
WrappedBaseObject
<
BaseObject
>
*>
(
base
);
if
(
wrappedObject
->
owner
==
WrappedObjectOwner
::
Internal
)
wrappedObject
->
cppPtr
.
reset
();
}
// ---------------------------------------------------------------------------
// Casts.
// ---------------------------------------------------------------------------
...
...
@@ -178,6 +204,20 @@ public:
return
cppObject
->
getPrivate
();
}
// ---------------------------------------------------------------------------
// Deal with cpp ptr destruction.
// ---------------------------------------------------------------------------
template
<
typename
CppType
,
typename
=
typename
std
::
enable_if
<
std
::
is_base_of
<
BaseObject
,
CppType
>
::
value
,
CppType
>::
type
>
static
void
signalCppPtrDestruction
(
CppType
*
cppObject
)
{
void
*
value
=
cppObject
->
getCBackPtr
();
if
(
value
&&
static_cast
<
WrappedBaseObject
<
CppType
>
*>
(
value
)
->
owner
==
WrappedObjectOwner
::
Internal
)
belle_sip_object_unref
(
value
);
}
// ---------------------------------------------------------------------------
// Get c/cpp ptr helpers.
// ---------------------------------------------------------------------------
...
...
@@ -187,12 +227,19 @@ public:
typename
CppType
=
typename
CTypeMetaInfo
<
CType
>
::
cppType
,
typename
=
typename
std
::
enable_if
<
IsDefinedBaseCppObject
<
CppType
>::
value
,
CppType
>::
type
>
static
L_INTERNAL_WRAPPER_CONSTEXPR
std
::
shared_ptr
<
CppType
>
getCppPtrFromC
(
CType
*
cObject
)
{
static
inline
std
::
shared_ptr
<
CppType
>
getCppPtrFromC
(
CType
*
cObject
)
{
#ifdef DEBUG
typedef
typename
CTypeMetaInfo
<
CType
>::
cppType
BaseType
;
typedef
CppType
DerivedType
;
std
::
shared_ptr
<
BaseType
>
cppObject
=
reinterpret_cast
<
WrappedBaseObject
<
BaseType
>
*>
(
cObject
)
->
cppPtr
;
std
::
shared_ptr
<
BaseType
>
cppObject
;
{
WrappedBaseObject
<
BaseType
>
*
wrappedObject
=
reinterpret_cast
<
WrappedBaseObject
<
BaseType
>
*>
(
cObject
);
cppObject
=
wrappedObject
->
owner
==
WrappedObjectOwner
::
Internal
?
wrappedObject
->
weakCppPtr
.
lock
()
:
wrappedObject
->
cppPtr
;
}
if
(
!
cppObject
)
abort
(
"Cpp Object is null."
);
...
...
@@ -202,7 +249,10 @@ public:
return
derivedCppObject
;
#else
return
reinterpret_cast
<
WrappedBaseObject
<
CppType
>
*>
(
cObject
)
->
cppPtr
;
WrappedBaseObject
<
CppType
>
*
wrappedObject
=
reinterpret_cast
<
WrappedBaseObject
<
CppType
>
*>
(
cObject
);
return
wrappedObject
->
owner
==
WrappedObjectOwner
::
Internal
?
wrappedObject
->
weakCppPtr
.
lock
()
:
wrappedObject
->
cppPtr
;
#endif
}
...
...
@@ -211,12 +261,8 @@ public:
typename
CppType
=
typename
CTypeMetaInfo
<
CType
>
::
cppType
,
typename
=
typename
std
::
enable_if
<
IsDefinedBaseCppObject
<
CppType
>::
value
,
CppType
>::
type
>
static
L_INTERNAL_WRAPPER_CONSTEXPR
std
::
shared_ptr
<
const
CppType
>
getCppPtrFromC
(
const
CType
*
cObject
)
{
#ifdef DEBUG
return
getCppPtrFromC
<
CType
,
CppType
>
(
const_cast
<
CType
*>
(
cObject
));
#else
return
reinterpret_cast
<
const
WrappedBaseObject
<
CppType
>
*>
(
cObject
)
->
cppPtr
;
#endif
static
inline
std
::
shared_ptr
<
const
CppType
>
getCppPtrFromC
(
const
CType
*
cObject
)
{
return
getCppPtrFromC
<
CType
,
CppType
>
(
const_cast
<
CType
*>
(
cObject
));
}
template
<
...
...
@@ -266,7 +312,23 @@ public:
typename
=
typename
std
::
enable_if
<
IsDefinedBaseCppObject
<
CppType
>::
value
,
CppType
>::
type
>
static
inline
void
setCppPtrFromC
(
CType
*
cObject
,
const
std
::
shared_ptr
<
CppType
>
&
cppObject
)
{
reinterpret_cast
<
WrappedBaseObject
<
CppType
>
*>
(
cObject
)
->
cppPtr
=
cppObject
;
WrappedBaseObject
<
CppType
>
*
wrappedObject
=
reinterpret_cast
<
WrappedBaseObject
<
CppType
>
*>
(
cObject
);
std
::
shared_ptr
<
CppType
>
oldCppObject
;
if
(
wrappedObject
->
owner
==
WrappedObjectOwner
::
Internal
)
{
oldCppObject
=
wrappedObject
->
weakCppPtr
.
lock
();
wrappedObject
->
weakCppPtr
=
cppObject
;
if
(
reinterpret_cast
<
belle_sip_object_t
*>
(
cObject
)
->
ref
>
1
)
wrappedObject
->
cppPtr
=
cppObject
;
else
wrappedObject
->
cppPtr
.
reset
();
}
else
{
oldCppObject
=
wrappedObject
->
cppPtr
;
wrappedObject
->
cppPtr
=
cppObject
;
}
if
(
oldCppObject
)
oldCppObject
->
setCBackPtr
(
nullptr
);
cppObject
->
setCBackPtr
(
cObject
);
}
...
...
@@ -295,7 +357,8 @@ public:
}
// ---------------------------------------------------------------------------
// Get c back ptr helpers.
// Get cpp ptr (shared if BaseObject, not shared if ClonableObject)
// from cpp object.
// ---------------------------------------------------------------------------
template
<
...
...
@@ -328,13 +391,23 @@ public:
return
cppObject
;
}
// ---------------------------------------------------------------------------
// Get c back ptr resolver helpers.
// ---------------------------------------------------------------------------
template
<
typename
CppType
,
typename
=
typename
std
::
enable_if
<
IsDefinedCppObject
<
CppType
>
::
value
||
IsDefinedClonableCppObject
<
CppType
>::
value
,
CppType
>::
type
typename
=
typename
std
::
enable_if
<
IsDefinedBaseCppObject
<
CppType
>
::
value
,
CppType
>::
type
>
static
inline
typename
CppTypeMetaInfo
<
CppType
>::
cType
*
getCBackPtr
(
const
CppType
*
cppObject
)
{
static
inline
typename
CppTypeMetaInfo
<
CppType
>::
cType
*
getCBackPtrResolver
(
const
std
::
shared_ptr
<
CppType
>
&
cppObject
)
{
return
getCBackPtr
(
cppObject
);
}
template
<
typename
CppType
,
typename
=
typename
std
::
enable_if
<
IsDefinedClonableCppObject
<
CppType
>
::
value
,
CppType
>::
type
>
static
inline
typename
CppTypeMetaInfo
<
CppType
>::
cType
*
getCBackPtrResolver
(
const
CppType
*
cppObject
)
{
if
(
L_UNLIKELY
(
!
cppObject
))
return
nullptr
;
...
...
@@ -345,13 +418,25 @@ public:
return
static_cast
<
RetType
*>
(
value
);
RetType
*
cObject
=
CppTypeMetaInfo
<
CppType
>::
init
();
// Can be set only on Object or ClonableObject. Not BaseObject.
setCppPtrFromC
(
cObject
,
getResolvedCppPtr
(
cppObject
));
setCppPtrFromC
(
cObject
,
cppObject
);
return
cObject
;
}
// ---------------------------------------------------------------------------
// Get c back ptr helpers.
// ---------------------------------------------------------------------------
template
<
typename
CppType
,
typename
=
typename
std
::
enable_if
<
IsDefinedCppObject
<
CppType
>
::
value
||
IsDefinedClonableCppObject
<
CppType
>::
value
,
CppType
>::
type
>
static
inline
typename
CppTypeMetaInfo
<
CppType
>::
cType
*
getCBackPtr
(
const
CppType
*
cppObject
)
{
return
getCBackPtrResolver
(
getResolvedCppPtr
(
cppObject
));
}
template
<
typename
CppType
,
typename
=
typename
std
::
enable_if
<
IsDefinedBaseCppObject
<
CppType
>
::
value
,
CppType
>::
type
...
...
@@ -367,6 +452,7 @@ public:
return
static_cast
<
RetType
*>
(
value
);
RetType
*
cObject
=
CppTypeMetaInfo
<
CppType
>::
init
();
reinterpret_cast
<
WrappedBaseObject
<
CppType
>
*>
(
cObject
)
->
owner
=
WrappedObjectOwner
::
Internal
;
setCppPtrFromC
(
cObject
,
cppObject
);
...
...
@@ -470,25 +556,38 @@ LINPHONE_END_NAMESPACE
#define L_INTERNAL_C_OBJECT_NO_XTOR(C_OBJECT)
#define L_INTERNAL_DECLARE_C_OBJECT(C_TYPE, CPP_TYPE, ...) \
struct _Linphone ## C_TYPE { \
belle_sip_object_t base; \
std::shared_ptr<L_CPP_TYPE_OF_C_TYPE(C_TYPE)> cppPtr; \
std::weak_ptr<L_CPP_TYPE_OF_C_TYPE(C_TYPE)> weakCppPtr; \
int owner; \
__VA_ARGS__ \
};
#define L_INTERNAL_DECLARE_C_OBJECT_FUNCTIONS(C_TYPE, CONSTRUCTOR, DESTRUCTOR) \
BELLE_SIP_DECLARE_VPTR_NO_EXPORT(Linphone ## C_TYPE); \
Linphone ## C_TYPE *_linphone_ ## C_TYPE ## _init () { \
Linphone ## C_TYPE * object = belle_sip_object_new(Linphone ## C_TYPE); \
new(&object->cppPtr) std::shared_ptr<L_CPP_TYPE_OF_C_TYPE(C_TYPE)>(); \
new(&object->weakCppPtr) std::weak_ptr<L_CPP_TYPE_OF_C_TYPE(C_TYPE)>(); \
CONSTRUCTOR(object); \
return object; \
} \
static void _linphone_ ## C_TYPE ## _uninit(Linphone ## C_TYPE * object) { \
DESTRUCTOR(object); \
object->cppPtr.~shared_ptr (); \
object->cppPtr.~shared_ptr(); \
object->weakCppPtr.~weak_ptr(); \
} \
BELLE_SIP_DECLARE_NO_IMPLEMENTED_INTERFACES(Linphone ## C_TYPE); \
BELLE_SIP_INSTANCIATE_VPTR( \
BELLE_SIP_INSTANCIATE_VPTR
2
( \
Linphone ## C_TYPE, \
belle_sip_object_t, \
_linphone_ ## C_TYPE ## _uninit, \
NULL, \
NULL, \
LinphonePrivate::Wrapper::onBelleSipFirstRef, \
LinphonePrivate::Wrapper::onBelleSipLastRef, \
FALSE \
);
...
...
@@ -551,21 +650,14 @@ LINPHONE_END_NAMESPACE
// Declare wrapped C object with constructor/destructor.
#define L_DECLARE_C_OBJECT_IMPL_WITH_XTORS(C_TYPE, CONSTRUCTOR, DESTRUCTOR, ...) \
struct _Linphone ## C_TYPE { \
belle_sip_object_t base; \
std::shared_ptr<L_CPP_TYPE_OF_C_TYPE(C_TYPE)> cppPtr; \
__VA_ARGS__ \
}; \
static_assert(LinphonePrivate::CTypeMetaInfo<Linphone ## C_TYPE>::defined, "Type is not defined."); \
L_INTERNAL_DECLARE_C_OBJECT(C_TYPE, L_CPP_TYPE_OF_C_TYPE(C_TYPE), __VA_ARGS__) \
L_INTERNAL_DECLARE_C_OBJECT_FUNCTIONS(C_TYPE, CONSTRUCTOR, DESTRUCTOR)
// Declare wrapped C object.
#define L_DECLARE_C_OBJECT_IMPL(C_TYPE, ...) \
static_assert(LinphonePrivate::CTypeMetaInfo<Linphone ## C_TYPE>::defined, "Type is not defined."); \
struct _Linphone ## C_TYPE { \
belle_sip_object_t base; \
std::shared_ptr<L_CPP_TYPE_OF_C_TYPE(C_TYPE)> cppPtr; \
__VA_ARGS__ \
}; \
L_INTERNAL_DECLARE_C_OBJECT(C_TYPE, L_CPP_TYPE_OF_C_TYPE(C_TYPE), __VA_ARGS__) \
L_INTERNAL_DECLARE_C_OBJECT_FUNCTIONS(C_TYPE, L_INTERNAL_C_OBJECT_NO_XTOR, L_INTERNAL_C_OBJECT_NO_XTOR)
// Declare clonable wrapped C object.
...
...
@@ -607,6 +699,10 @@ LINPHONE_END_NAMESPACE
// Call the init function of wrapped C object.
#define L_INIT(C_TYPE) _linphone_ ## C_TYPE ## _init()
// Signal to wrapper the destruction of cpp base object.
#define L_SIGNAL_CPP_PTR_DESTRUCTION(CPP_OBJECT) \
LinphonePrivate::Wrapper::signalCppPtrDestruction(CPP_OBJECT);
// Get/set the cpp-ptr of a wrapped C object.
#define L_GET_CPP_PTR_FROM_C_OBJECT_1_ARGS(C_OBJECT) \
LinphonePrivate::Wrapper::getCppPtrFromC(C_OBJECT)
...
...
src/object/base-object.cpp
View file @
fcbce751
...
...
@@ -19,6 +19,9 @@
#include "base-object-p.h"
// Necessary for: L_SIGNAL_CPP_PTR_DESTRUCTION.
#include "c-wrapper/internal/c-tools.h"
#include "base-object.h"
// =============================================================================
...
...
@@ -32,6 +35,7 @@ BaseObject::BaseObject (BaseObjectPrivate &p) : mPrivate(&p) {
}
BaseObject
::~
BaseObject
()
{
L_SIGNAL_CPP_PTR_DESTRUCTION
(
this
);
delete
mPrivate
;
}
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment