mirror of
https://gitlab.linphone.org/BC/public/linphone-iphone.git
synced 2026-01-27 07:59:20 +00:00
feat(core): provide a shareable data in ClonableObject, assignment operator is supported by events, ...
This commit is contained in:
parent
1610aa411e
commit
d0048a553d
22 changed files with 460 additions and 65 deletions
|
|
@ -32,6 +32,9 @@ set(LINPHONE_CXX_OBJECTS_PRIVATE_HEADER_FILES
|
|||
db/abstract/abstract-db-p.h
|
||||
db/abstract/abstract-db.h
|
||||
db/events-db.h
|
||||
db/provider/db-session-p.h
|
||||
db/provider/db-session-provider.h
|
||||
db/provider/db-session.h
|
||||
enums.h
|
||||
event/call-event.h
|
||||
event/event.h
|
||||
|
|
@ -56,6 +59,8 @@ set(LINPHONE_CXX_OBJECTS_SOURCE_FILES
|
|||
cpim/parser/cpim-parser.cpp
|
||||
db/abstract/abstract-db.cpp
|
||||
db/events-db.cpp
|
||||
db/provider/db-session-provider.cpp
|
||||
db/provider/db-session.cpp
|
||||
event/call-event.cpp
|
||||
event/event.cpp
|
||||
event/message-event.cpp
|
||||
|
|
|
|||
|
|
@ -19,11 +19,8 @@
|
|||
#ifndef _ABSTRACT_DB_P_H_
|
||||
#define _ABSTRACT_DB_P_H_
|
||||
|
||||
#ifdef SOCI_ENABLED
|
||||
#include <soci/soci.h>
|
||||
#endif // ifdef SOCI_ENABLED
|
||||
|
||||
#include "abstract-db.h"
|
||||
#include "db/provider/db-session.h"
|
||||
#include "object/object-p.h"
|
||||
|
||||
// =============================================================================
|
||||
|
|
@ -32,13 +29,10 @@ LINPHONE_BEGIN_NAMESPACE
|
|||
|
||||
class AbstractDbPrivate : public ObjectPrivate {
|
||||
public:
|
||||
#ifdef SOCI_ENABLED
|
||||
soci::session session;
|
||||
#endif // ifndef SOCI_ENABLED
|
||||
DbSession dbSession;
|
||||
|
||||
private:
|
||||
AbstractDb::Backend backend;
|
||||
bool isConnected = false;
|
||||
|
||||
L_DECLARE_PUBLIC(AbstractDb);
|
||||
};
|
||||
|
|
|
|||
|
|
@ -17,43 +17,34 @@
|
|||
*/
|
||||
|
||||
#include "abstract-db-p.h"
|
||||
#include "db/provider/db-session-provider.h"
|
||||
#include "logger/logger.h"
|
||||
|
||||
#include "abstract-db.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
// =============================================================================
|
||||
|
||||
using namespace std;
|
||||
|
||||
LINPHONE_BEGIN_NAMESPACE
|
||||
|
||||
AbstractDb::AbstractDb (AbstractDbPrivate &p) : Object(*new AbstractDbPrivate) {}
|
||||
|
||||
bool AbstractDb::connect (Backend backend, const std::string ¶meters) {
|
||||
#ifdef SOCI_ENABLED
|
||||
L_D(AbstractDb);
|
||||
try {
|
||||
if (d->isConnected) {
|
||||
d->session.close();
|
||||
d->isConnected = false;
|
||||
}
|
||||
bool AbstractDb::connect (Backend backend, const string ¶meters) {
|
||||
L_D(AbstractDb);
|
||||
|
||||
d->session.open(backend == Mysql ? "mysql" : "sqlite3", parameters);
|
||||
init();
|
||||
} catch (const exception &e) {
|
||||
return false;
|
||||
}
|
||||
d->dbSession = DbSessionProvider::getInstance()->getSession(
|
||||
(backend == Mysql ? "mysql://" : "sqlite3://") + parameters
|
||||
);
|
||||
|
||||
return true;
|
||||
#else
|
||||
lWarning() << "Cannot use AbstractDb. Soci is not enabled.";
|
||||
return false;
|
||||
#endif // ifndef SOCI_ENABLED
|
||||
if (d->dbSession)
|
||||
init();
|
||||
return d->dbSession;
|
||||
}
|
||||
|
||||
bool AbstractDb::isConnected () const {
|
||||
L_D(const AbstractDb);
|
||||
return d->isConnected;
|
||||
return d->dbSession;
|
||||
}
|
||||
|
||||
AbstractDb::Backend AbstractDb::getBackend () const {
|
||||
|
|
|
|||
|
|
@ -20,6 +20,11 @@
|
|||
|
||||
#include "events-db.h"
|
||||
|
||||
// TODO: Remove me.
|
||||
#ifdef SOCI_ENABLED
|
||||
#undef SOCI_ENABLED
|
||||
#endif
|
||||
|
||||
// =============================================================================
|
||||
|
||||
LINPHONE_BEGIN_NAMESPACE
|
||||
|
|
@ -61,10 +66,10 @@ void EventsDb::init () {
|
|||
|
||||
d->session <<
|
||||
"CREATE TABLE IF NOT EXISTS dialog ("
|
||||
" local_sip_address_id BIGINT UNSIGNED NOT NULL," // Sip address used to communicate.
|
||||
" remote_sip_address_id BIGINT UNSIGNED NOT NULL," // Server (for conference) or user sip address.
|
||||
" creation_timestamp TIMESTAMP NOT NULL," // Dialog creation date.
|
||||
" last_update_timestamp TIMESTAMP NOT NULL," // Last event timestamp (call, message...).
|
||||
" local_sip_address_id BIGINT UNSIGNED NOT NULL," // Sip address used to communicate.
|
||||
" remote_sip_address_id BIGINT UNSIGNED NOT NULL," // Server (for conference) or user sip address.
|
||||
" creation_timestamp TIMESTAMP NOT NULL," // Dialog creation date.
|
||||
" last_update_timestamp TIMESTAMP NOT NULL," // Last event timestamp (call, message...).
|
||||
" FOREIGN KEY (local_sip_address_id)"
|
||||
" REFERENCES sip_address(id)"
|
||||
" ON DELETE CASCADE,"
|
||||
|
|
@ -79,7 +84,7 @@ void EventsDb::init () {
|
|||
" dialog_id BIGINT UNSIGNED NOT NULL,"
|
||||
" status_id TINYINT UNSIGNED NOT NULL,"
|
||||
" direction_id TINYINT UNSIGNED NOT NULL,"
|
||||
" imdn_message_id VARCHAR(255) NOT NULL," // See: https://tools.ietf.org/html/rfc5438#section-6.3
|
||||
" imdn_message_id VARCHAR(255) NOT NULL," // See: https://tools.ietf.org/html/rfc5438#section-6.3
|
||||
" content_type VARCHAR(255) NOT NULL,"
|
||||
" is_secured BOOLEAN NOT NULL,"
|
||||
" app_data VARCHAR(2048),"
|
||||
|
|
|
|||
54
src/db/provider/db-session-p.h
Normal file
54
src/db/provider/db-session-p.h
Normal file
|
|
@ -0,0 +1,54 @@
|
|||
/*
|
||||
* db-session-p.h
|
||||
* Copyright (C) 2017 Belledonne Communications SARL
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef _DB_SESSION_P_H_
|
||||
#define _DB_SESSION_P_H_
|
||||
|
||||
#ifdef SOCI_ENABLED
|
||||
#include <memory>
|
||||
#endif // ifdef SOCI_ENABLED
|
||||
|
||||
#include "db-session.h"
|
||||
#include "object/clonable-object-p.h"
|
||||
|
||||
// =============================================================================
|
||||
|
||||
#ifdef SOCI_ENABLED
|
||||
namespace soci {
|
||||
class session;
|
||||
}
|
||||
#endif // ifdef SOCI_ENABLED
|
||||
|
||||
LINPHONE_BEGIN_NAMESPACE
|
||||
|
||||
class DbSessionPrivate : public ClonableObjectPrivate {
|
||||
friend class DbSessionProvider;
|
||||
|
||||
private:
|
||||
bool isValid = false;
|
||||
|
||||
#ifdef SOCI_ENABLED
|
||||
std::shared_ptr<soci::session> session;
|
||||
#endif // ifndef SOCI_ENABLED
|
||||
|
||||
L_DECLARE_PUBLIC(DbSession);
|
||||
};
|
||||
|
||||
LINPHONE_END_NAMESPACE
|
||||
|
||||
#endif // ifndef _DB_SESSION_P_H_
|
||||
83
src/db/provider/db-session-provider.cpp
Normal file
83
src/db/provider/db-session-provider.cpp
Normal file
|
|
@ -0,0 +1,83 @@
|
|||
/*
|
||||
* db-session-provider.cpp
|
||||
* Copyright (C) 2017 Belledonne Communications SARL
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifdef SOCI_ENABLED
|
||||
#include <unordered_map>
|
||||
|
||||
#include <soci/soci.h>
|
||||
#endif // ifdef SOCI_ENABLED
|
||||
|
||||
#include "db-session-p.h"
|
||||
#include "object/object-p.h"
|
||||
|
||||
#include "db-session-provider.h"
|
||||
|
||||
#define CLEAN_COUNTER_MAX 1000
|
||||
|
||||
// =============================================================================
|
||||
|
||||
using namespace std;
|
||||
|
||||
LINPHONE_BEGIN_NAMESPACE
|
||||
|
||||
class DbSessionProviderPrivate : public ObjectPrivate {
|
||||
public:
|
||||
#ifdef SOCI_ENABLED
|
||||
typedef pair<weak_ptr<soci::session>, DbSessionPrivate *> InternalSession;
|
||||
unordered_map<string, InternalSession> sessions;
|
||||
#endif // ifdef SOCI_ENABLED
|
||||
|
||||
int cleanCounter = 0;
|
||||
};
|
||||
|
||||
DbSessionProvider::DbSessionProvider () : Singleton(*new DbSessionProviderPrivate) {}
|
||||
|
||||
DbSession DbSessionProvider::getSession (const string &uri) {
|
||||
DbSession session;
|
||||
|
||||
#ifdef SOCI_ENABLED
|
||||
L_D(DbSessionProvider);
|
||||
try {
|
||||
shared_ptr<soci::session> sociSession = d->sessions[uri].first.lock();
|
||||
if (!sociSession) { // Create new session.
|
||||
sociSession = make_shared<soci::session>(uri);
|
||||
DbSessionPrivate *p = session.getPrivate();
|
||||
p->session = sociSession;
|
||||
p->isValid = true;
|
||||
d->sessions[uri] = make_pair(sociSession, p);
|
||||
} else // Share session.
|
||||
session.setRef(*d->sessions[uri].second);
|
||||
} catch (const exception &) {}
|
||||
|
||||
// Remove invalid weak ptrs.
|
||||
if (++d->cleanCounter >= CLEAN_COUNTER_MAX) {
|
||||
d->cleanCounter = 0;
|
||||
|
||||
for (auto it = d->sessions.begin(), itEnd = d->sessions.end(); it != itEnd;) {
|
||||
if (it->second.first.expired())
|
||||
it = d->sessions.erase(it);
|
||||
else
|
||||
++it;
|
||||
}
|
||||
}
|
||||
#endif // ifndef SOCI_ENABLED
|
||||
|
||||
return session;
|
||||
}
|
||||
|
||||
LINPHONE_END_NAMESPACE
|
||||
48
src/db/provider/db-session-provider.h
Normal file
48
src/db/provider/db-session-provider.h
Normal file
|
|
@ -0,0 +1,48 @@
|
|||
/*
|
||||
* db-session-provider.h
|
||||
* Copyright (C) 2017 Belledonne Communications SARL
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef _DB_SESSION_PROVIDER_H_
|
||||
#define _DB_SESSION_PROVIDER_H_
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "db-session.h"
|
||||
#include "object/singleton.h"
|
||||
|
||||
// =============================================================================
|
||||
|
||||
LINPHONE_BEGIN_NAMESPACE
|
||||
|
||||
class DbSessionProviderPrivate;
|
||||
|
||||
class DbSessionProvider : public Singleton<DbSessionProvider> {
|
||||
friend class Singleton<DbSessionProvider>;
|
||||
|
||||
public:
|
||||
DbSession getSession (const std::string &uri);
|
||||
|
||||
private:
|
||||
DbSessionProvider ();
|
||||
|
||||
L_DECLARE_PRIVATE(DbSessionProvider);
|
||||
L_DISABLE_COPY(DbSessionProvider);
|
||||
};
|
||||
|
||||
LINPHONE_END_NAMESPACE
|
||||
|
||||
#endif // ifndef _DB_SESSION_PROVIDER_H_
|
||||
36
src/db/provider/db-session.cpp
Normal file
36
src/db/provider/db-session.cpp
Normal file
|
|
@ -0,0 +1,36 @@
|
|||
/*
|
||||
* db-session.cpp
|
||||
* Copyright (C) 2017 Belledonne Communications SARL
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "db-session-p.h"
|
||||
|
||||
#include "db-session.h"
|
||||
|
||||
// =============================================================================
|
||||
|
||||
using namespace std;
|
||||
|
||||
LINPHONE_BEGIN_NAMESPACE
|
||||
|
||||
L_USE_DEFAULT_SHARE_IMPL(DbSession, ClonableObject);
|
||||
|
||||
DbSession::operator bool () const {
|
||||
L_D(const DbSession);
|
||||
return d->isValid;
|
||||
}
|
||||
|
||||
LINPHONE_END_NAMESPACE
|
||||
49
src/db/provider/db-session.h
Normal file
49
src/db/provider/db-session.h
Normal file
|
|
@ -0,0 +1,49 @@
|
|||
/*
|
||||
* db-session.h
|
||||
* Copyright (C) 2017 Belledonne Communications SARL
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef _DB_SESSION_H_
|
||||
#define _DB_SESSION_H_
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "object/clonable-object.h"
|
||||
|
||||
// =============================================================================
|
||||
|
||||
LINPHONE_BEGIN_NAMESPACE
|
||||
|
||||
class DbSessionPrivate;
|
||||
|
||||
class DbSession : public ClonableObject {
|
||||
friend class DbSessionProvider;
|
||||
|
||||
public:
|
||||
DbSession ();
|
||||
DbSession (const DbSession &src);
|
||||
|
||||
DbSession &operator= (const DbSession &src);
|
||||
|
||||
operator bool () const;
|
||||
|
||||
private:
|
||||
L_DECLARE_PRIVATE(DbSession);
|
||||
};
|
||||
|
||||
LINPHONE_END_NAMESPACE
|
||||
|
||||
#endif // ifndef _DB_SESSION_H_
|
||||
|
|
@ -41,6 +41,16 @@ CallEvent::CallEvent (Type type, const shared_ptr<Call> &call) : Event(*new Call
|
|||
|
||||
CallEvent::CallEvent (const CallEvent &src) : CallEvent(src.getType(), src.getCall()) {}
|
||||
|
||||
CallEvent &CallEvent::operator= (const CallEvent &src) {
|
||||
L_D(CallEvent);
|
||||
if (this != &src) {
|
||||
Event::operator=(src);
|
||||
d->call = src.getPrivate()->call;
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
shared_ptr<Call> CallEvent::getCall () const {
|
||||
L_D(const CallEvent);
|
||||
return d->call;
|
||||
|
|
|
|||
|
|
@ -35,6 +35,8 @@ public:
|
|||
CallEvent (Type type, const std::shared_ptr<Call> &message);
|
||||
CallEvent (const CallEvent &src);
|
||||
|
||||
CallEvent &operator= (const CallEvent &src);
|
||||
|
||||
std::shared_ptr<Call> getCall () const;
|
||||
|
||||
private:
|
||||
|
|
|
|||
|
|
@ -24,15 +24,24 @@
|
|||
|
||||
LINPHONE_BEGIN_NAMESPACE
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
Event::Event () : ClonableObject(*new EventPrivate) {}
|
||||
|
||||
Event::Event (const Event &) : ClonableObject(*new EventPrivate) {}
|
||||
|
||||
Event::Event (EventPrivate &p, Type type) : ClonableObject(p) {
|
||||
Event::Event (EventPrivate &p, Type type) : ClonableObject(*new EventPrivate) {
|
||||
L_D(Event);
|
||||
d->type = type;
|
||||
}
|
||||
|
||||
Event &Event::operator= (const Event &src) {
|
||||
L_D(Event);
|
||||
if (this != &src)
|
||||
d->type = src.getPrivate()->type;
|
||||
return *this;
|
||||
}
|
||||
|
||||
Event::Type Event::getType () const {
|
||||
L_D(const Event);
|
||||
return d->type;
|
||||
|
|
|
|||
|
|
@ -40,6 +40,8 @@ public:
|
|||
Event (const Event &src);
|
||||
virtual ~Event () = default;
|
||||
|
||||
Event &operator= (const Event &src);
|
||||
|
||||
Type getType () const;
|
||||
|
||||
protected:
|
||||
|
|
|
|||
|
|
@ -41,6 +41,16 @@ MessageEvent::MessageEvent (const shared_ptr<Message> &message) : Event(*new Mes
|
|||
|
||||
MessageEvent::MessageEvent (const MessageEvent &src) : MessageEvent(src.getMessage()) {}
|
||||
|
||||
MessageEvent &MessageEvent::operator= (const MessageEvent &src) {
|
||||
L_D(MessageEvent);
|
||||
if (this != &src) {
|
||||
Event::operator=(src);
|
||||
d->message = src.getPrivate()->message;
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
shared_ptr<Message> MessageEvent::getMessage () const {
|
||||
L_D(const MessageEvent);
|
||||
return d->message;
|
||||
|
|
|
|||
|
|
@ -35,6 +35,8 @@ public:
|
|||
MessageEvent (const std::shared_ptr<Message> &message);
|
||||
MessageEvent (const MessageEvent &src);
|
||||
|
||||
MessageEvent &operator= (const MessageEvent &src);
|
||||
|
||||
std::shared_ptr<Message> getMessage () const;
|
||||
|
||||
private:
|
||||
|
|
|
|||
|
|
@ -19,22 +19,27 @@
|
|||
#ifndef _CLONABLE_OBJECT_P_H_
|
||||
#define _CLONABLE_OBJECT_P_H_
|
||||
|
||||
#include <unordered_map>
|
||||
|
||||
#include "utils/general.h"
|
||||
|
||||
// =============================================================================
|
||||
|
||||
LINPHONE_BEGIN_NAMESPACE
|
||||
|
||||
class ClonableObject;
|
||||
|
||||
class ClonableObjectPrivate {
|
||||
public:
|
||||
virtual ~ClonableObjectPrivate () = default;
|
||||
|
||||
protected:
|
||||
ClonableObject *mPublic = nullptr;
|
||||
std::unordered_map<const ClonableObjectPrivate *, ClonableObject *> *mPublic = nullptr;
|
||||
|
||||
private:
|
||||
void ref ();
|
||||
void unref ();
|
||||
|
||||
int nRefs = 0;
|
||||
|
||||
L_DECLARE_PUBLIC(ClonableObject);
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -20,16 +20,67 @@
|
|||
|
||||
#include "clonable-object.h"
|
||||
|
||||
LINPHONE_BEGIN_NAMESPACE
|
||||
|
||||
// =============================================================================
|
||||
|
||||
using namespace std;
|
||||
|
||||
LINPHONE_BEGIN_NAMESPACE
|
||||
|
||||
// TODO: Use atomic counter?
|
||||
|
||||
void ClonableObjectPrivate::ref () {
|
||||
++nRefs;
|
||||
}
|
||||
|
||||
void ClonableObjectPrivate::unref () {
|
||||
if (--nRefs == 0) {
|
||||
delete mPublic;
|
||||
delete this;
|
||||
}
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
ClonableObject::ClonableObject (ClonableObjectPrivate &p) : mPrivate(&p) {
|
||||
mPrivate->mPublic = this;
|
||||
// Q-pointer must be empty. It's a constructor that takes a new private data.
|
||||
L_ASSERT(!mPrivate->mPublic);
|
||||
|
||||
mPrivate->mPublic = new remove_pointer<decltype(mPrivate->mPublic)>::type;
|
||||
(*mPrivate->mPublic)[mPrivate] = this;
|
||||
mPrivate->ref();
|
||||
}
|
||||
|
||||
ClonableObject::ClonableObject (const ClonableObjectPrivate &p) {
|
||||
// Cannot access to Q-pointer. It's a copy constructor from private data.
|
||||
L_ASSERT(!mPrivate);
|
||||
|
||||
setRef(p);
|
||||
}
|
||||
|
||||
ClonableObject::~ClonableObject () {
|
||||
delete mPrivate;
|
||||
mPrivate->mPublic->erase(mPrivate);
|
||||
mPrivate->unref();
|
||||
}
|
||||
|
||||
void ClonableObject::setRef (const ClonableObjectPrivate &p) {
|
||||
// Q-pointer must exist.
|
||||
L_ASSERT(mPrivate);
|
||||
L_ASSERT(mPrivate->mPublic);
|
||||
|
||||
// Nothing, same reference.
|
||||
if (&p == mPrivate)
|
||||
return;
|
||||
|
||||
// Unref previous private data.
|
||||
if (mPrivate) {
|
||||
mPrivate->mPublic->erase(mPrivate);
|
||||
mPrivate->unref();
|
||||
}
|
||||
|
||||
// Add and reference new private data.
|
||||
mPrivate = const_cast<ClonableObjectPrivate *>(&p);
|
||||
(*mPrivate->mPublic)[mPrivate] = this;
|
||||
mPrivate->ref();
|
||||
}
|
||||
|
||||
LINPHONE_END_NAMESPACE
|
||||
|
|
|
|||
|
|
@ -25,15 +25,20 @@
|
|||
|
||||
LINPHONE_BEGIN_NAMESPACE
|
||||
|
||||
class ClonableObjectPrivate;
|
||||
|
||||
class LINPHONE_PUBLIC ClonableObject {
|
||||
public:
|
||||
virtual ~ClonableObject ();
|
||||
|
||||
protected:
|
||||
// Use a new ClonableObjectPrivate without owner.
|
||||
explicit ClonableObject (ClonableObjectPrivate &p);
|
||||
|
||||
// If you want share an existing ClonableObjectPrivate, call this function.
|
||||
explicit ClonableObject (const ClonableObjectPrivate &p);
|
||||
|
||||
// Change the ClonableObjectPrivate, it can be shared.
|
||||
void setRef (const ClonableObjectPrivate &p);
|
||||
|
||||
ClonableObjectPrivate *mPrivate = nullptr;
|
||||
|
||||
private:
|
||||
|
|
|
|||
|
|
@ -25,8 +25,6 @@
|
|||
|
||||
LINPHONE_BEGIN_NAMESPACE
|
||||
|
||||
class Object;
|
||||
|
||||
class ObjectPrivate {
|
||||
public:
|
||||
virtual ~ObjectPrivate () = default;
|
||||
|
|
|
|||
|
|
@ -25,8 +25,6 @@
|
|||
|
||||
LINPHONE_BEGIN_NAMESPACE
|
||||
|
||||
class ObjectPrivate;
|
||||
|
||||
class LINPHONE_PUBLIC Object {
|
||||
public:
|
||||
virtual ~Object ();
|
||||
|
|
|
|||
|
|
@ -47,6 +47,14 @@ LINPHONE_BEGIN_NAMESPACE
|
|||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
void l_assert (const char *condition, const char *file, int line);
|
||||
|
||||
#ifdef DEBUG
|
||||
#define L_ASSERT(CONDITION) static_cast<void>(false && (CONDITION))
|
||||
#else
|
||||
#define L_ASSERT(CONDITION) ((CONDITION) ? static_cast<void>(0) : l_assert(#CONDITION, __FILE__, __LINE__))
|
||||
#endif
|
||||
|
||||
#define L_DECLARE_PRIVATE(CLASS) \
|
||||
inline CLASS ## Private * getPrivate() { \
|
||||
return reinterpret_cast<CLASS ## Private *>(mPrivate); \
|
||||
|
|
@ -56,12 +64,41 @@ LINPHONE_BEGIN_NAMESPACE
|
|||
} \
|
||||
friend class CLASS ## Private;
|
||||
|
||||
class ClonableObject;
|
||||
class ClonableObjectPrivate;
|
||||
class Object;
|
||||
class ObjectPrivate;
|
||||
|
||||
template<typename T>
|
||||
inline ClonableObject *getPublicHelper (T *object, ClonableObjectPrivate *context) {
|
||||
auto it = object->find(context);
|
||||
L_ASSERT(it != object->end());
|
||||
return it->second;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
inline const ClonableObject *getPublicHelper (const T *object, const ClonableObjectPrivate *context) {
|
||||
auto it = object->find(context);
|
||||
L_ASSERT(it != object->cend());
|
||||
return it->second;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
inline Object *getPublicHelper (T *object, ObjectPrivate *) {
|
||||
return object;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
inline const Object *getPublicHelper (const T *object, const ObjectPrivate *) {
|
||||
return object;
|
||||
}
|
||||
|
||||
#define L_DECLARE_PUBLIC(CLASS) \
|
||||
inline CLASS * getPublic() { \
|
||||
return static_cast<CLASS *>(mPublic); \
|
||||
inline CLASS * getPublic () { \
|
||||
return static_cast<CLASS *>(getPublicHelper(mPublic, this)); \
|
||||
} \
|
||||
inline const CLASS *getPublic() const { \
|
||||
return static_cast<const CLASS *>(mPublic); \
|
||||
inline const CLASS *getPublic () const { \
|
||||
return static_cast<const CLASS *>(getPublicHelper(mPublic, this)); \
|
||||
} \
|
||||
friend class CLASS;
|
||||
|
||||
|
|
@ -72,13 +109,14 @@ LINPHONE_BEGIN_NAMESPACE
|
|||
#define L_D(CLASS) CLASS ## Private * const d = getPrivate();
|
||||
#define L_Q(CLASS) CLASS * const q = getPublic();
|
||||
|
||||
void l_assert (const char *condition, const char *file, int line);
|
||||
|
||||
#ifdef DEBUG
|
||||
#define L_ASSERT(CONDITION) static_cast<void>(false && (CONDITION))
|
||||
#else
|
||||
#define L_ASSERT(CONDITION) ((CONDITION) ? static_cast<void>(0) : l_assert(#CONDITION, __FILE__, __LINE__))
|
||||
#endif
|
||||
#define L_USE_DEFAULT_SHARE_IMPL(CLASS, PARENT_CLASS) \
|
||||
CLASS::CLASS () : PARENT_CLASS(*new CLASS ## Private) {} \
|
||||
CLASS::CLASS (const CLASS &src) : ClonableObject(*src.getPrivate()) {} \
|
||||
CLASS &CLASS::operator= (const CLASS &src) { \
|
||||
if (this != &src) \
|
||||
setRef(*src.getPrivate()); \
|
||||
return *this; \
|
||||
}
|
||||
|
||||
LINPHONE_END_NAMESPACE
|
||||
|
||||
|
|
|
|||
|
|
@ -29,15 +29,15 @@
|
|||
LINPHONE_BEGIN_NAMESPACE
|
||||
|
||||
namespace Utils {
|
||||
LINPHONE_PUBLIC bool iequals (const std::string &a, const std::string &b);
|
||||
LINPHONE_PUBLIC bool iequals (const std::string &a, const std::string &b);
|
||||
|
||||
LINPHONE_PUBLIC std::vector<std::string> split (const std::string &str, const std::string &delimiter);
|
||||
LINPHONE_PUBLIC std::vector<std::string> split (const std::string &str, const std::string &delimiter);
|
||||
|
||||
LINPHONE_PUBLIC inline std::vector<std::string> split (const std::string &str, char delimiter) {
|
||||
return split(str, std::string(1, delimiter));
|
||||
}
|
||||
LINPHONE_PUBLIC inline std::vector<std::string> split (const std::string &str, char delimiter) {
|
||||
return split(str, std::string(1, delimiter));
|
||||
}
|
||||
|
||||
LINPHONE_PUBLIC int stoi (const std::string &str, size_t *idx = 0, int base = 10);
|
||||
LINPHONE_PUBLIC int stoi (const std::string &str, size_t *idx = 0, int base = 10);
|
||||
}
|
||||
|
||||
LINPHONE_END_NAMESPACE
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue