forked from romixlab/qmsgpack
Thread safety implemented for registerPacker and registerUnpacker
This commit is contained in:
@@ -11,6 +11,7 @@
|
|||||||
|
|
||||||
QHash<QMetaType::Type, MsgPackPrivate::packer_t> MsgPackPrivate::user_packers;
|
QHash<QMetaType::Type, MsgPackPrivate::packer_t> MsgPackPrivate::user_packers;
|
||||||
bool MsgPackPrivate::compatibilityMode = false;
|
bool MsgPackPrivate::compatibilityMode = false;
|
||||||
|
QReadWriteLock MsgPackPrivate::packers_lock;
|
||||||
|
|
||||||
quint8 *MsgPackPrivate::pack(const QVariant &v, quint8 *p, bool wr)
|
quint8 *MsgPackPrivate::pack(const QVariant &v, quint8 *p, bool wr)
|
||||||
{
|
{
|
||||||
@@ -38,7 +39,12 @@ quint8 *MsgPackPrivate::pack(const QVariant &v, quint8 *p, bool wr)
|
|||||||
else if (t == QMetaType::QVariantMap)
|
else if (t == QMetaType::QVariantMap)
|
||||||
p = pack_map(v.toMap(), p, wr);
|
p = pack_map(v.toMap(), p, wr);
|
||||||
else {
|
else {
|
||||||
if (user_packers.contains(t))
|
if (t == QMetaType::User)
|
||||||
|
t = (QMetaType::Type)v.userType();
|
||||||
|
packers_lock.lockForRead();
|
||||||
|
bool has_packer = user_packers.contains(t);
|
||||||
|
packers_lock.unlock();
|
||||||
|
if (has_packer)
|
||||||
p = pack_user(v, p, wr);
|
p = pack_user(v, p, wr);
|
||||||
else
|
else
|
||||||
qWarning() << "MsgPack::pack can't pack type:" << t;
|
qWarning() << "MsgPack::pack can't pack type:" << t;
|
||||||
@@ -269,21 +275,23 @@ quint8 *MsgPackPrivate::pack_map(const QVariantMap &map, quint8 *p, bool wr)
|
|||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool MsgPackPrivate::register_packer(QMetaType::Type q_type, qint8 msgpack_type, MsgPack::pack_user_f packer)
|
bool MsgPackPrivate::register_packer(QMetaType::Type q_type, qint8 msgpack_type, MsgPack::pack_user_f packer)
|
||||||
{
|
{
|
||||||
if (user_packers.contains(q_type)) {
|
|
||||||
qWarning() << "MsgPack::packer for qtype" << q_type << "already exist";
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (packer == 0) {
|
if (packer == 0) {
|
||||||
qWarning() << "MsgPack::packer for qtype" << q_type << "is invalid";
|
qWarning() << "MsgPack::packer for qtype" << q_type << "is invalid";
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
packers_lock.lockForWrite();
|
||||||
|
if (user_packers.contains(q_type)) {
|
||||||
|
qWarning() << "MsgPack::packer for qtype" << q_type << "already exist";
|
||||||
|
packers_lock.unlock();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
packer_t p;
|
packer_t p;
|
||||||
p.packer = packer;
|
p.packer = packer;
|
||||||
p.type = msgpack_type;
|
p.type = msgpack_type;
|
||||||
user_packers.insert(q_type, p);
|
user_packers.insert(q_type, p);
|
||||||
|
packers_lock.unlock();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -292,7 +300,9 @@ quint8 *MsgPackPrivate::pack_user(const QVariant &v, quint8 *p, bool wr)
|
|||||||
QMetaType::Type t = (QMetaType::Type)v.type() == QMetaType::User ?
|
QMetaType::Type t = (QMetaType::Type)v.type() == QMetaType::User ?
|
||||||
(QMetaType::Type)v.userType() : (QMetaType::Type)v.type();
|
(QMetaType::Type)v.userType() : (QMetaType::Type)v.type();
|
||||||
QByteArray data;
|
QByteArray data;
|
||||||
|
packers_lock.lockForRead();
|
||||||
packer_t pt = user_packers[t];
|
packer_t pt = user_packers[t];
|
||||||
|
packers_lock.unlock();
|
||||||
quint32 len = pt.packer(v, data, wr);
|
quint32 len = pt.packer(v, data, wr);
|
||||||
if (len == 1) {
|
if (len == 1) {
|
||||||
if (wr) *p = 0xd4;
|
if (wr) *p = 0xd4;
|
||||||
@@ -331,4 +341,3 @@ quint8 *MsgPackPrivate::pack_user(const QVariant &v, quint8 *p, bool wr)
|
|||||||
memcpy(p, data.data(), len);
|
memcpy(p, data.data(), len);
|
||||||
return p += len;
|
return p += len;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -5,6 +5,7 @@
|
|||||||
|
|
||||||
#include <QHash>
|
#include <QHash>
|
||||||
#include <QMetaType>
|
#include <QMetaType>
|
||||||
|
#include <QReadWriteLock>
|
||||||
|
|
||||||
class QByteArray;
|
class QByteArray;
|
||||||
class QString;
|
class QString;
|
||||||
@@ -19,6 +20,7 @@ typedef struct {
|
|||||||
} packer_t;
|
} packer_t;
|
||||||
bool register_packer(QMetaType::Type q_type, qint8 msgpack_type, MsgPack::pack_user_f packer);
|
bool register_packer(QMetaType::Type q_type, qint8 msgpack_type, MsgPack::pack_user_f packer);
|
||||||
extern QHash<QMetaType::Type, packer_t> user_packers;
|
extern QHash<QMetaType::Type, packer_t> user_packers;
|
||||||
|
extern QReadWriteLock packers_lock;
|
||||||
extern bool compatibilityMode;
|
extern bool compatibilityMode;
|
||||||
|
|
||||||
quint8 * pack(const QVariant &v, quint8 *p, bool wr);
|
quint8 * pack(const QVariant &v, quint8 *p, bool wr);
|
||||||
|
@@ -21,6 +21,7 @@ MsgPackPrivate::type_parser_f MsgPackPrivate::unpackers[32] = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
QHash<qint8, MsgPack::unpack_user_f> MsgPackPrivate::user_unpackers;
|
QHash<qint8, MsgPack::unpack_user_f> MsgPackPrivate::user_unpackers;
|
||||||
|
QReadWriteLock MsgPackPrivate::unpackers_lock;
|
||||||
|
|
||||||
QVariant MsgPackPrivate::unpack(quint8 *p, quint8 *end)
|
QVariant MsgPackPrivate::unpack(quint8 *p, quint8 *end)
|
||||||
{
|
{
|
||||||
@@ -314,12 +315,14 @@ quint8 * MsgPackPrivate::unpack_map32(QVariant &v, quint8 *p)
|
|||||||
|
|
||||||
quint8 *MsgPackPrivate::unpack_ext(QVariant &v, quint8 *p, qint8 type, quint32 len)
|
quint8 *MsgPackPrivate::unpack_ext(QVariant &v, quint8 *p, qint8 type, quint32 len)
|
||||||
{
|
{
|
||||||
|
unpackers_lock.lockForRead();
|
||||||
if (!user_unpackers.contains(type)) {
|
if (!user_unpackers.contains(type)) {
|
||||||
qWarning() << "MsgPack::unpack() unpacker for type" << type << "doesn't exist";
|
qWarning() << "MsgPack::unpack() unpacker for type" << type << "doesn't exist";
|
||||||
return p + len;
|
return p + len;
|
||||||
}
|
}
|
||||||
QByteArray data((char *)p, len);
|
QByteArray data((char *)p, len);
|
||||||
v = user_unpackers[type](data);
|
v = user_unpackers[type](data);
|
||||||
|
unpackers_lock.unlock();
|
||||||
return p + len;
|
return p + len;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -382,14 +385,17 @@ quint8 * MsgPackPrivate::unpack_ext32(QVariant &v, quint8 *p)
|
|||||||
|
|
||||||
bool MsgPackPrivate::register_unpacker(qint8 msgpack_type, MsgPack::unpack_user_f unpacker)
|
bool MsgPackPrivate::register_unpacker(qint8 msgpack_type, MsgPack::unpack_user_f unpacker)
|
||||||
{
|
{
|
||||||
if (user_unpackers.contains(msgpack_type)) {
|
|
||||||
qWarning() << "MsgPack::unpacker for type" << msgpack_type << "already exists";
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (unpacker == 0) {
|
if (unpacker == 0) {
|
||||||
qWarning() << "MsgPack::unpacker for type" << msgpack_type << "is invalid";
|
qWarning() << "MsgPack::unpacker for type" << msgpack_type << "is invalid";
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
unpackers_lock.lockForWrite();
|
||||||
|
if (user_unpackers.contains(msgpack_type)) {
|
||||||
|
qWarning() << "MsgPack::unpacker for type" << msgpack_type << "already exists";
|
||||||
|
unpackers_lock.unlock();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
user_unpackers.insert(msgpack_type, unpacker);
|
user_unpackers.insert(msgpack_type, unpacker);
|
||||||
|
unpackers_lock.unlock();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@@ -5,6 +5,7 @@
|
|||||||
|
|
||||||
#include <QHash>
|
#include <QHash>
|
||||||
#include <QVariant>
|
#include <QVariant>
|
||||||
|
#include <QReadWriteLock>
|
||||||
|
|
||||||
namespace MsgPackPrivate
|
namespace MsgPackPrivate
|
||||||
{
|
{
|
||||||
@@ -19,6 +20,7 @@ extern type_parser_f unpackers[32];
|
|||||||
|
|
||||||
bool register_unpacker(qint8 msgpack_type, MsgPack::unpack_user_f unpacker);
|
bool register_unpacker(qint8 msgpack_type, MsgPack::unpack_user_f unpacker);
|
||||||
extern QHash<qint8, MsgPack::unpack_user_f> user_unpackers;
|
extern QHash<qint8, MsgPack::unpack_user_f> user_unpackers;
|
||||||
|
extern QReadWriteLock unpackers_lock;
|
||||||
|
|
||||||
// goes from p to end unpacking types with unpack_type function below
|
// goes from p to end unpacking types with unpack_type function below
|
||||||
QVariant unpack(quint8 *p, quint8 *end);
|
QVariant unpack(quint8 *p, quint8 *end);
|
||||||
|
@@ -90,9 +90,11 @@ void MixedTest::test_ext()
|
|||||||
QVariant custom;
|
QVariant custom;
|
||||||
custom.setValue(ct);
|
custom.setValue(ct);
|
||||||
|
|
||||||
MsgPack::registerPacker((QMetaType::Type)qMetaTypeId<CustomType>(),
|
bool packer_registered = MsgPack::registerPacker((QMetaType::Type)qMetaTypeId<CustomType>(),
|
||||||
3, pack_custom_type);
|
3, pack_custom_type);
|
||||||
MsgPack::registerUnpacker(3, unpack_custom_type);
|
QVERIFY(packer_registered);
|
||||||
|
bool unpacker_registered = MsgPack::registerUnpacker(3, unpack_custom_type);
|
||||||
|
QVERIFY(unpacker_registered);
|
||||||
|
|
||||||
QByteArray arr = MsgPack::pack(custom);
|
QByteArray arr = MsgPack::pack(custom);
|
||||||
QVERIFY(arr.size() == 2 + ct.size());
|
QVERIFY(arr.size() == 2 + ct.size());
|
||||||
|
Reference in New Issue
Block a user