Fix JSON API event handler registering behavior

As a bonus the behaviour is now homogeneous between C++ API and JSON API
Fix a bunch of compiler warning
RsEvents implementation is now safer
mHandlerMaps size is known at compile time, so use an std::array instead
  of vector
This commit is contained in:
Gioacchino Mazzurco 2020-04-01 19:34:49 +02:00
parent ce5f5faa97
commit 4c0baa1ec3
No known key found for this signature in database
GPG Key ID: A1FBCA3872E87051
17 changed files with 165 additions and 139 deletions

View File

@ -108,14 +108,6 @@ p3discovery2::p3discovery2(
// Add self into PGP FriendList. // Add self into PGP FriendList.
mFriendList[AuthGPG::getAuthGPG()->getGPGOwnId()] = DiscPgpInfo(); mFriendList[AuthGPG::getAuthGPG()->getGPGOwnId()] = DiscPgpInfo();
if(rsEvents)
rsEvents->registerEventsHandler(
RsEventType::GOSSIP_DISCOVERY,
[this](std::shared_ptr<const RsEvent> event)
{
rsEventsHandler(*event);
}, mRsEventsHandle ); // mRsEventsHandle is zeroed in initializer list
} }
@ -1280,11 +1272,6 @@ bool p3discovery2::setPeerVersion(const RsPeerId &peerId, const std::string &ver
return true; return true;
} }
void p3discovery2::rsEventsHandler(const RsEvent& event)
{
Dbg3() << __PRETTY_FUNCTION__ << " " << static_cast<uint32_t>(event.mType) << std::endl;
}
/*************************************************************************************/ /*************************************************************************************/
/* AuthGPGService */ /* AuthGPGService */

View File

@ -352,7 +352,7 @@ JsonApiServer::JsonApiServer(): configMutex("JsonApiServer config"),
rsEvents, "rsEvents", cAns, session ) ) rsEvents, "rsEvents", cAns, session ) )
return; return;
RsEventType eventType = RsEventType::NONE; RsEventType eventType = RsEventType::__NONE;
// deserialize input parameters from JSON // deserialize input parameters from JSON
{ {
@ -395,7 +395,8 @@ JsonApiServer::JsonApiServer(): configMutex("JsonApiServer config"),
} ); } );
}; };
bool retval = rsEvents->registerEventsHandler(eventType,multiCallback, hId); bool retval = rsEvents->registerEventsHandler(
multiCallback, hId, eventType );
{ {
RsGenericSerializer::SerializeContext& ctx(cAns); RsGenericSerializer::SerializeContext& ctx(cAns);

View File

@ -50,7 +50,7 @@ extern RsEvents* rsEvents;
*/ */
enum class RsEventType : uint32_t enum class RsEventType : uint32_t
{ {
NONE = 0, /// Used to detect uninitialized event __NONE = 0, /// Used internally to detect invalid event type passed
/// @see RsBroadcastDiscovery /// @see RsBroadcastDiscovery
BROADCAST_DISCOVERY = 1, BROADCAST_DISCOVERY = 1,
@ -64,7 +64,7 @@ enum class RsEventType : uint32_t
/// @see pqissl /// @see pqissl
PEER_CONNECTION = 4, PEER_CONNECTION = 4,
/// @see RsGxsChanges // this one is used in RsGxsBroadcast /// @see RsGxsChanges, used also in @see RsGxsBroadcast
GXS_CHANGES = 5, GXS_CHANGES = 5,
/// Emitted when a peer state changes, @see RsPeers /// Emitted when a peer state changes, @see RsPeers
@ -95,9 +95,9 @@ enum class RsEventType : uint32_t
FILE_TRANSFER = 14, FILE_TRANSFER = 14,
/// @see RsMsgs /// @see RsMsgs
CHAT_MESSAGE = 15, CHAT_MESSAGE = 15,
MAX /// Used to detect invalid event type passed __MAX /// Used internally to detect invalid event type passed
}; };
/** /**
@ -107,7 +107,7 @@ enum class RsEventType : uint32_t
struct RsEvent : RsSerializable struct RsEvent : RsSerializable
{ {
protected: protected:
RsEvent(RsEventType type) : explicit RsEvent(RsEventType type) :
mType(type), mTimePoint(std::chrono::system_clock::now()) {} mType(type), mTimePoint(std::chrono::system_clock::now()) {}
RsEvent() = delete; RsEvent() = delete;
@ -174,8 +174,9 @@ public:
* @brief Register events handler * @brief Register events handler
* Every time an event is dispatced the registered events handlers will get * Every time an event is dispatced the registered events handlers will get
* their method handleEvent called with the event passed as paramether. * their method handleEvent called with the event passed as paramether.
* @attention Callbacks must not fiddle internally with methods of this
* class otherwise a deadlock will happen.
* @jsonapi{development,manualwrapper} * @jsonapi{development,manualwrapper}
* @param eventType Type of event for which the callback is called
* @param multiCallback Function that will be called each time an event * @param multiCallback Function that will be called each time an event
* is dispatched. * is dispatched.
* @param[inout] hId Optional storage for handler id, useful to * @param[inout] hId Optional storage for handler id, useful to
@ -183,13 +184,15 @@ public:
* value may be provided to the function call but * value may be provided to the function call but
* must habe been generated with * must habe been generated with
* @see generateUniqueHandlerId() * @see generateUniqueHandlerId()
* @param eventType Optional type of event for which the callback is
* called, if NONE is passed multiCallback is
* called for every events without filtering.
* @return False on error, true otherwise. * @return False on error, true otherwise.
*/ */
virtual bool registerEventsHandler( virtual bool registerEventsHandler(
RsEventType eventType,
std::function<void(std::shared_ptr<const RsEvent>)> multiCallback, std::function<void(std::shared_ptr<const RsEvent>)> multiCallback,
RsEventsHandlerId_t& hId = RS_DEFAULT_STORAGE_PARAM(RsEventsHandlerId_t, 0) RsEventsHandlerId_t& hId = RS_DEFAULT_STORAGE_PARAM(RsEventsHandlerId_t, 0),
) = 0; RsEventType eventType = RsEventType::__NONE ) = 0;
/** /**
* @brief Unregister event handler * @brief Unregister event handler
@ -200,4 +203,3 @@ public:
virtual ~RsEvents(); virtual ~RsEvents();
}; };

View File

@ -39,7 +39,7 @@ bool isEventValid(
return false; return false;
} }
if(event->mType <= RsEventType::NONE) if(event->mType <= RsEventType::__NONE)
{ {
errorMessage = "Event has type NONE: " + errorMessage = "Event has type NONE: " +
std::to_string( std::to_string(
@ -48,9 +48,9 @@ bool isEventValid(
return false; return false;
} }
if(event->mType >= RsEventType::MAX) if(event->mType >= RsEventType::__MAX)
{ {
errorMessage = "Event has type >= RsEventType::MAX: " + errorMessage = "Event has type >= RsEventType::__MAX: " +
std::to_string( std::to_string(
static_cast<std::underlying_type<RsEventType>::type >( static_cast<std::underlying_type<RsEventType>::type >(
event->mType ) ); event->mType ) );
@ -100,25 +100,30 @@ RsEventsHandlerId_t RsEventsService::generateUniqueHandlerId_unlocked()
} }
bool RsEventsService::registerEventsHandler( bool RsEventsService::registerEventsHandler(
RsEventType eventType,
std::function<void(std::shared_ptr<const RsEvent>)> multiCallback, std::function<void(std::shared_ptr<const RsEvent>)> multiCallback,
RsEventsHandlerId_t& hId ) RsEventsHandlerId_t& hId, RsEventType eventType )
{ {
RS_STACK_MUTEX(mHandlerMapMtx); RS_STACK_MUTEX(mHandlerMapMtx);
if( (int)eventType > mHandlerMaps.size() + 10) if( eventType >= RsEventType::__MAX)
{ {
RsErr() << "Cannot register an event handler for an event type larger than 10 plus the max pre-defined event (value passed was " << (int)eventType << " whereas max is " << (int)RsEventType::MAX << ")" << std::endl; RsErr() << __PRETTY_FUNCTION__ << " Invalid event type: "
return false; << static_cast<uint32_t>(eventType) << " >= RsEventType::__MAX:"
} << static_cast<uint32_t>(RsEventType::__MAX) << std::endl;
print_stacktrace();
return false;
}
if( (int)eventType >= mHandlerMaps.size()) if(!hId) hId = generateUniqueHandlerId_unlocked();
mHandlerMaps.resize( (int)eventType +1 ); else if (hId > mLastHandlerId)
{
RsErr() << __PRETTY_FUNCTION__ << " Invalid handler id: " << hId
<< " how did you generate it? " << std::endl;
print_stacktrace();
return false;
}
if(!hId) mHandlerMaps[static_cast<std::size_t>(eventType)][hId] = multiCallback;
hId = generateUniqueHandlerId_unlocked();
mHandlerMaps[(int)eventType][hId] = multiCallback;
return true; return true;
} }
@ -126,14 +131,14 @@ bool RsEventsService::unregisterEventsHandler(RsEventsHandlerId_t hId)
{ {
RS_STACK_MUTEX(mHandlerMapMtx); RS_STACK_MUTEX(mHandlerMapMtx);
for(uint32_t i=0;i<mHandlerMaps.size();++i) for(uint32_t i=0; i<mHandlerMaps.size(); ++i)
{ {
auto it = mHandlerMaps[i].find(hId); auto it = mHandlerMaps[i].find(hId);
if(it != mHandlerMaps[i].end()) if(it != mHandlerMaps[i].end())
{ {
mHandlerMaps[i].erase(it); mHandlerMaps[i].erase(it);
return true; return true;
} }
} }
return false; return false;
} }
@ -174,27 +179,29 @@ dispatchEventFromQueueLock:
void RsEventsService::handleEvent(std::shared_ptr<const RsEvent> event) void RsEventsService::handleEvent(std::shared_ptr<const RsEvent> event)
{ {
std::function<void(std::shared_ptr<const RsEvent>)> mCallback; uint32_t event_type_index = static_cast<uint32_t>(event->mType);
uint32_t event_type_index = static_cast<uint32_t>(event->mType); if(RsEventType::__NONE >= event->mType || event->mType >= RsEventType::__MAX )
{
RsErr() << __PRETTY_FUNCTION__ << " Invalid event type: "
<< event_type_index << std::endl;
print_stacktrace();
return;
}
{ {
RS_STACK_MUTEX(mHandlerMapMtx); /* LOCKED AREA */ RS_STACK_MUTEX(mHandlerMapMtx);
/* It is important to also call the callback under mutex protection to
* ensure they are not unregistered in the meanwhile.
* If a callback try to fiddle with registering/unregistering it will
* deadlock */
if(event_type_index >= mHandlerMaps.size() || event_type_index < 1) // Call all clients that registered a callback for this event type
{ for(auto cbit: mHandlerMaps[event_type_index]) cbit.second(event);
RsErr() << "Cannot handle an event of type " << event_type_index << ": out of scope!" << std::endl;
return;
}
// Call all clients that registered a callback for this event type /* Also call all clients that registered with NONE, meaning that they
* expect all events */
for(auto cbit: mHandlerMaps[event_type_index]) for(auto cbit: mHandlerMaps[static_cast<uint32_t>(RsEventType::__NONE)])
cbit.second(event); cbit.second(event);
// Also call all clients that registered with NONE, meaning that they expect all events
for(auto cbit: mHandlerMaps[static_cast<uint32_t>(RsEventType::NONE)])
cbit.second(event);
} }
} }

View File

@ -3,7 +3,8 @@
* * * *
* libretroshare: retroshare core library * * libretroshare: retroshare core library *
* * * *
* Copyright (C) 2019 Gioacchino Mazzurco <gio@eigenlab.org> * * Copyright (C) 2019-2020 Gioacchino Mazzurco <gio@eigenlab.org> *
* Copyright (C) 2020 Asociación Civil Altermundi <info@altermundi.net> *
* * * *
* This program is free software: you can redistribute it and/or modify * * This program is free software: you can redistribute it and/or modify *
* it under the terms of the GNU Lesser General Public License as * * it under the terms of the GNU Lesser General Public License as *
@ -24,6 +25,7 @@
#include <memory> #include <memory>
#include <cstdint> #include <cstdint>
#include <deque> #include <deque>
#include <array>
#include "retroshare/rsevents.h" #include "retroshare/rsevents.h"
#include "util/rsthreads.h" #include "util/rsthreads.h"
@ -35,7 +37,6 @@ class RsEventsService :
public: public:
RsEventsService(): RsEventsService():
mHandlerMapMtx("RsEventsService::mHandlerMapMtx"), mLastHandlerId(1), mHandlerMapMtx("RsEventsService::mHandlerMapMtx"), mLastHandlerId(1),
mHandlerMaps(static_cast<int>(RsEventType::MAX)),
mEventQueueMtx("RsEventsService::mEventQueueMtx") {} mEventQueueMtx("RsEventsService::mEventQueueMtx") {}
/// @see RsEvents /// @see RsEvents
@ -55,10 +56,9 @@ public:
/// @see RsEvents /// @see RsEvents
bool registerEventsHandler( bool registerEventsHandler(
RsEventType eventType,
std::function<void(std::shared_ptr<const RsEvent>)> multiCallback, std::function<void(std::shared_ptr<const RsEvent>)> multiCallback,
RsEventsHandlerId_t& hId = RS_DEFAULT_STORAGE_PARAM(RsEventsHandlerId_t, 0) RsEventsHandlerId_t& hId = RS_DEFAULT_STORAGE_PARAM(RsEventsHandlerId_t, 0),
) override; RsEventType eventType = RsEventType::__NONE ) override;
/// @see RsEvents /// @see RsEvents
bool unregisterEventsHandler(RsEventsHandlerId_t hId) override; bool unregisterEventsHandler(RsEventsHandlerId_t hId) override;
@ -67,10 +67,12 @@ protected:
RsMutex mHandlerMapMtx; RsMutex mHandlerMapMtx;
RsEventsHandlerId_t mLastHandlerId; RsEventsHandlerId_t mLastHandlerId;
std::vector< std::array<
std::map< std::map<
RsEventsHandlerId_t, RsEventsHandlerId_t,
std::function<void(std::shared_ptr<const RsEvent>)> > > mHandlerMaps; std::function<void(std::shared_ptr<const RsEvent>)> >,
static_cast<std::size_t>(RsEventType::__MAX)
> mHandlerMaps;
RsMutex mEventQueueMtx; RsMutex mEventQueueMtx;
std::deque< std::shared_ptr<const RsEvent> > mEventQueue; std::deque< std::shared_ptr<const RsEvent> > mEventQueue;

View File

@ -1076,30 +1076,36 @@ TransfersDialog::TransfersDialog(QWidget *parent)
// load settings // load settings
processSettings(true); processSettings(true);
int S = QFontMetricsF(font()).height(); int S = static_cast<int>(QFontMetricsF(font()).height());
QString help_str = tr( QString help_str = tr(
" <h1><img width=\"%1\" src=\":/icons/help_64.png\">&nbsp;&nbsp;File Transfer</h1> \ "<h1><img width=\"%1\" src=\":/icons/help_64.png\">&nbsp;&nbsp;"
<p>Retroshare brings two ways of transferring files: direct transfers from your friends, and \ "File Transfer</h1>"
distant anonymous tunnelled transfers. In addition, file transfer is multi-source and allows swarming \ "<p>Retroshare brings two ways of transferring files: direct "
(you can be a source while downloading)</p> \ "transfers from your friends, and distant anonymous tunnelled "
<p>You can share files using the <img src=\":/images/directoryadd_24x24_shadow.png\" width=%2 /> icon from the left side bar. \ "transfers. In addition, file transfer is multi-source and "
These files will be listed in the My Files tab. You can decide for each friend group whether they can or not see these files \ "allows swarming (you can be a source while downloading)</p>"
in their Friends Files tab</p>\ "<p>You can share files using the "
<p>The search tab reports files from your friends' file lists, and distant files that can be reached \ "<img src=\":/images/directoryadd_24x24_shadow.png\" width=%2 />"
anonymously using the multi-hop tunnelling system.</p> \ " icon from the left side bar. These files will be listed in "
").arg(QString::number(2*S)).arg(QString::number(S)) ; "the My Files tab. You can decide for each friend group whether"
" they can or not see these files in their Friends Files tab</p>"
"<p>The search tab reports files from your friends' file lists,"
" and distant files that can be reached anonymously using the "
"multi-hop tunnelling system.</p>")
.arg(QString::number(2*S)).arg(QString::number(S)) ;
registerHelpButton(ui.helpButton,help_str,"TransfersDialog") ; registerHelpButton(ui.helpButton,help_str,"TransfersDialog") ;
mEventHandlerId=0; mEventHandlerId=0;
rsEvents->registerEventsHandler(RsEventType::FILE_TRANSFER, [this](std::shared_ptr<const RsEvent> event) { handleEvent(event); }, mEventHandlerId ); rsEvents->registerEventsHandler(
[this](std::shared_ptr<const RsEvent> event) { handleEvent(event); },
mEventHandlerId, RsEventType::FILE_TRANSFER );
} }
void TransfersDialog::handleEvent(std::shared_ptr<const RsEvent> event) void TransfersDialog::handleEvent(std::shared_ptr<const RsEvent> event)
{ {
if(event->mType != RsEventType::FILE_TRANSFER) if(event->mType != RsEventType::FILE_TRANSFER) return;
return;
const RsFileTransferEvent *fe = dynamic_cast<const RsFileTransferEvent*>(event.get()); const RsFileTransferEvent *fe = dynamic_cast<const RsFileTransferEvent*>(event.get());
if(!fe) if(!fe)

View File

@ -149,11 +149,17 @@ IdDialog::IdDialog(QWidget *parent) : MainPage(parent), ui(new Ui::IdDialog)
{ {
ui->setupUi(this); ui->setupUi(this);
mEventHandlerId_identity = 0; mEventHandlerId_identity = 0;
rsEvents->registerEventsHandler(RsEventType::GXS_IDENTITY, [this](std::shared_ptr<const RsEvent> event) { RsQThreadUtils::postToObject( [=]() { handleEvent_main_thread(event); }, this ); }, mEventHandlerId_identity ); rsEvents->registerEventsHandler(
[this](std::shared_ptr<const RsEvent> event)
{ RsQThreadUtils::postToObject([=](){ handleEvent_main_thread(event); }, this); },
mEventHandlerId_identity, RsEventType::GXS_IDENTITY );
mEventHandlerId_circles = 0; mEventHandlerId_circles = 0;
rsEvents->registerEventsHandler(RsEventType::GXS_CIRCLES, [this](std::shared_ptr<const RsEvent> event) { RsQThreadUtils::postToObject( [=]() { handleEvent_main_thread(event); }, this ); }, mEventHandlerId_circles ); rsEvents->registerEventsHandler(
[this](std::shared_ptr<const RsEvent> event)
{ RsQThreadUtils::postToObject([=](){ handleEvent_main_thread(event); }, this); },
mEventHandlerId_circles, RsEventType::GXS_CIRCLES );
// This is used to grab the broadcast of changes from p3GxsCircles, which is discarded by the current dialog, since it expects data for p3Identity only. // This is used to grab the broadcast of changes from p3GxsCircles, which is discarded by the current dialog, since it expects data for p3Identity only.
//mCirclesBroadcastBase = new RsGxsUpdateBroadcastBase(rsGxsCircles, this); //mCirclesBroadcastBase = new RsGxsUpdateBroadcastBase(rsGxsCircles, this);

View File

@ -67,12 +67,11 @@
* #define NEWS_DEBUG 1 * #define NEWS_DEBUG 1
****/ ****/
static NewsFeed *instance = NULL; static NewsFeed* instance = nullptr;
/** Constructor */ /** Constructor */
NewsFeed::NewsFeed(QWidget *parent) : MainPage(parent), ui(new Ui::NewsFeed) NewsFeed::NewsFeed(QWidget *parent) : MainPage(parent), ui(new Ui::NewsFeed),
{ mEventTypes({
mEventTypes = {
RsEventType::AUTHSSL_CONNECTION_AUTENTICATION, RsEventType::AUTHSSL_CONNECTION_AUTENTICATION,
RsEventType::PEER_CONNECTION , RsEventType::PEER_CONNECTION ,
RsEventType::GXS_CIRCLES , RsEventType::GXS_CIRCLES ,
@ -80,12 +79,14 @@ NewsFeed::NewsFeed(QWidget *parent) : MainPage(parent), ui(new Ui::NewsFeed)
RsEventType::GXS_FORUMS , RsEventType::GXS_FORUMS ,
RsEventType::GXS_POSTED , RsEventType::GXS_POSTED ,
RsEventType::MAIL_STATUS RsEventType::MAIL_STATUS
}; })
{
for(uint32_t i=0;i<mEventTypes.size();++i) for(uint32_t i=0;i<mEventTypes.size();++i)
{ {
mEventHandlerIds.push_back(0); // needed to force intialization by registerEventsHandler() mEventHandlerIds.push_back(0); // needed to force intialization by registerEventsHandler()
rsEvents->registerEventsHandler(mEventTypes[i], [this](std::shared_ptr<const RsEvent> event) { handleEvent(event); }, mEventHandlerIds.back() ); rsEvents->registerEventsHandler(
[this](std::shared_ptr<const RsEvent> event) { handleEvent(event); },
mEventHandlerIds.back(), mEventTypes[i] );
} }
/* Invoke the Qt Designer generated object setup routine */ /* Invoke the Qt Designer generated object setup routine */

View File

@ -41,13 +41,14 @@ public:
}; };
/** Constructor */ /** Constructor */
PostedDialog::PostedDialog(QWidget *parent) PostedDialog::PostedDialog(QWidget *parent):
: GxsGroupFrameDialog(rsPosted, parent) GxsGroupFrameDialog(rsPosted, parent), mEventHandlerId(0)
{ {
mEventHandlerId = 0; // Needs to be asynced because this function is likely to be called by another thread!
// Needs to be asynced because this function is likely to be called by another thread! rsEvents->registerEventsHandler(
[this](std::shared_ptr<const RsEvent> event)
rsEvents->registerEventsHandler(RsEventType::GXS_POSTED, [this](std::shared_ptr<const RsEvent> event) { RsQThreadUtils::postToObject( [=]() { handleEvent_main_thread(event); }, this ); }, mEventHandlerId ); { RsQThreadUtils::postToObject( [=]() { handleEvent_main_thread(event); }, this ); },
mEventHandlerId, RsEventType::GXS_POSTED );
} }
void PostedDialog::handleEvent_main_thread(std::shared_ptr<const RsEvent> event) void PostedDialog::handleEvent_main_thread(std::shared_ptr<const RsEvent> event)

View File

@ -107,9 +107,11 @@ PostedListWidget::PostedListWidget(const RsGxsGroupId &postedId, QWidget *parent
processSettings(true); processSettings(true);
mEventHandlerId = 0; mEventHandlerId = 0;
// Needs to be asynced because this function is likely to be called by another thread! // Needs to be asynced because this function is called by another thread!
rsEvents->registerEventsHandler(
rsEvents->registerEventsHandler(RsEventType::GXS_POSTED, [this](std::shared_ptr<const RsEvent> event) { RsQThreadUtils::postToObject( [=]() { handleEvent_main_thread(event); }, this ); }, mEventHandlerId ); [this](std::shared_ptr<const RsEvent> event)
{ RsQThreadUtils::postToObject( [=]() { handleEvent_main_thread(event); }, this ); },
mEventHandlerId, RsEventType::GXS_POSTED );
/* Initialize GUI */ /* Initialize GUI */
setGroupId(postedId); setGroupId(postedId);

View File

@ -177,8 +177,10 @@ NewFriendList::NewFriendList(QWidget *parent) : /* RsAutoUpdatePage(5000,parent)
ui->filterLineEdit->setPlaceholderText(tr("Search")) ; ui->filterLineEdit->setPlaceholderText(tr("Search")) ;
ui->filterLineEdit->showFilterIcon(); ui->filterLineEdit->showFilterIcon();
mEventHandlerId=0; // forces initialization mEventHandlerId=0; // forces initialization
rsEvents->registerEventsHandler( RsEventType::PEER_CONNECTION, [this](std::shared_ptr<const RsEvent> e) { handleEvent(e); }, mEventHandlerId ); rsEvents->registerEventsHandler(
[this](std::shared_ptr<const RsEvent> e) { handleEvent(e); },
mEventHandlerId, RsEventType::PEER_CONNECTION );
mModel = new RsFriendListModel(); mModel = new RsFriendListModel();
mProxyModel = new FriendListSortFilterProxyModel(ui->peerTreeWidget->header(),this); mProxyModel = new FriendListSortFilterProxyModel(ui->peerTreeWidget->header(),this);

View File

@ -47,12 +47,14 @@
// }; // };
/** Constructor */ /** Constructor */
GxsChannelDialog::GxsChannelDialog(QWidget *parent) GxsChannelDialog::GxsChannelDialog(QWidget *parent):
: GxsGroupFrameDialog(rsGxsChannels, parent,true) GxsGroupFrameDialog(rsGxsChannels, parent, true), mEventHandlerId(0)
{ {
mEventHandlerId = 0; // Needs to be asynced because this function is called by another thread!
// Needs to be asynced because this function is likely to be called by another thread! rsEvents->registerEventsHandler(
rsEvents->registerEventsHandler(RsEventType::GXS_CHANNELS, [this](std::shared_ptr<const RsEvent> event) { RsQThreadUtils::postToObject( [=]() { handleEvent_main_thread(event); }, this ); }, mEventHandlerId ); [this](std::shared_ptr<const RsEvent> event)
{ RsQThreadUtils::postToObject([=]() { handleEvent_main_thread(event); }, this ); },
mEventHandlerId, RsEventType::GXS_CHANNELS );
} }
void GxsChannelDialog::handleEvent_main_thread(std::shared_ptr<const RsEvent> event) void GxsChannelDialog::handleEvent_main_thread(std::shared_ptr<const RsEvent> event)

View File

@ -130,9 +130,11 @@ GxsChannelPostsWidget::GxsChannelPostsWidget(const RsGxsGroupId &channelId, QWid
setGroupId(channelId); setGroupId(channelId);
mEventHandlerId = 0; mEventHandlerId = 0;
// Needs to be asynced because this function is likely to be called by another thread! // Needs to be asynced because this function is called by another thread!
rsEvents->registerEventsHandler(
rsEvents->registerEventsHandler(RsEventType::GXS_CHANNELS, [this](std::shared_ptr<const RsEvent> event) { RsQThreadUtils::postToObject( [=]() { handleEvent_main_thread(event); }, this ); }, mEventHandlerId ); [this](std::shared_ptr<const RsEvent> event)
{ RsQThreadUtils::postToObject([=](){ handleEvent_main_thread(event); }, this ); },
mEventHandlerId, RsEventType::GXS_CHANNELS );
} }
void GxsChannelPostsWidget::handleEvent_main_thread(std::shared_ptr<const RsEvent> event) void GxsChannelPostsWidget::handleEvent_main_thread(std::shared_ptr<const RsEvent> event)

View File

@ -345,10 +345,12 @@ GxsForumThreadWidget::GxsForumThreadWidget(const RsGxsGroupId &forumId, QWidget
ui->threadTreeWidget->enableColumnCustomize(true); ui->threadTreeWidget->enableColumnCustomize(true);
#endif #endif
mEventHandlerId = 0; mEventHandlerId = 0;
// Needs to be asynced because this function is likely to be called by another thread! // Needs to be asynced because this function is called by another thread!
rsEvents->registerEventsHandler(
rsEvents->registerEventsHandler(RsEventType::GXS_FORUMS, [this](std::shared_ptr<const RsEvent> event) { RsQThreadUtils::postToObject( [=]() { handleEvent_main_thread(event); }, this ); }, mEventHandlerId ); [this](std::shared_ptr<const RsEvent> event)
{ RsQThreadUtils::postToObject([=](){ handleEvent_main_thread(event); }, this ); },
mEventHandlerId, RsEventType::GXS_FORUMS );
} }
void GxsForumThreadWidget::handleEvent_main_thread(std::shared_ptr<const RsEvent> event) void GxsForumThreadWidget::handleEvent_main_thread(std::shared_ptr<const RsEvent> event)

View File

@ -38,14 +38,15 @@ public:
}; };
/** Constructor */ /** Constructor */
GxsForumsDialog::GxsForumsDialog(QWidget *parent) GxsForumsDialog::GxsForumsDialog(QWidget *parent) :
: GxsGroupFrameDialog(rsGxsForums, parent) GxsGroupFrameDialog(rsGxsForums, parent), mEventHandlerId(0)
{ {
mCountChildMsgs = true; mCountChildMsgs = true;
mEventHandlerId = 0;
// Needs to be asynced because this function is likely to be called by another thread!
rsEvents->registerEventsHandler(RsEventType::GXS_FORUMS, [this](std::shared_ptr<const RsEvent> event) { RsQThreadUtils::postToObject( [=]() { handleEvent_main_thread(event); }, this ); }, mEventHandlerId ); rsEvents->registerEventsHandler(
[this](std::shared_ptr<const RsEvent> event)
{ RsQThreadUtils::postToObject( [=]() { handleEvent_main_thread(event); }, this ); },
mEventHandlerId, RsEventType::GXS_FORUMS );
} }
void GxsForumsDialog::handleEvent_main_thread(std::shared_ptr<const RsEvent> event) void GxsForumsDialog::handleEvent_main_thread(std::shared_ptr<const RsEvent> event)

View File

@ -52,8 +52,10 @@ HashingStatus::HashingStatus(QWidget *parent)
hashloader->hide(); hashloader->hide();
statusHashing->hide(); statusHashing->hide();
mEventHandlerId=0; mEventHandlerId=0;
rsEvents->registerEventsHandler(RsEventType::SHARED_DIRECTORIES, [this](std::shared_ptr<const RsEvent> event) { handleEvent(event); }, mEventHandlerId ); rsEvents->registerEventsHandler(
[this](std::shared_ptr<const RsEvent> event) { handleEvent(event); },
mEventHandlerId, RsEventType::SHARED_DIRECTORIES );
} }
void HashingStatus::handleEvent(std::shared_ptr<const RsEvent> event) void HashingStatus::handleEvent(std::shared_ptr<const RsEvent> event)

View File

@ -1,7 +1,7 @@
/******************************************************************************* /*******************************************************************************
* util/RsGxsUpdateBroadcast.cpp * * util/RsGxsUpdateBroadcast.cpp *
* * * *
* Copyright (c) 2014 Retroshare Team <retroshare.project@gmail.com> * * Copyright (C) 2014-2020 Retroshare Team <contact@retroshare.cc> *
* * * *
* This program is free software: you can redistribute it and/or modify * * This program is free software: you can redistribute it and/or modify *
* it under the terms of the GNU Affero General Public License as * * it under the terms of the GNU Affero General Public License as *
@ -32,17 +32,17 @@
// now the update notify works through rsnotify and notifyqt // now the update notify works through rsnotify and notifyqt
// so the single instance per service is not really needed anymore // so the single instance per service is not really needed anymore
QMap<RsGxsIfaceHelper*, RsGxsUpdateBroadcast*> updateBroadcastMap; static QMap<RsGxsIfaceHelper*, RsGxsUpdateBroadcast*> updateBroadcastMap;
RsGxsUpdateBroadcast::RsGxsUpdateBroadcast(RsGxsIfaceHelper *ifaceImpl) : RsGxsUpdateBroadcast::RsGxsUpdateBroadcast(RsGxsIfaceHelper *ifaceImpl) :
QObject(NULL), mIfaceImpl(ifaceImpl) QObject(nullptr), mIfaceImpl(ifaceImpl), mEventHandlerId(0)
{ {
mEventHandlerId = 0; // forces initialization in registerEventsHandler() /* No need of postToObject here as onChangesReceived just emit signals
* internally */
rsEvents->registerEventsHandler(RsEventType::GXS_CHANGES, [this](std::shared_ptr<const RsEvent> event) rsEvents->registerEventsHandler(
{ [this](std::shared_ptr<const RsEvent> event)
onChangesReceived(*dynamic_cast<const RsGxsChanges*>(event.get())); { onChangesReceived(*dynamic_cast<const RsGxsChanges*>(event.get())); },
}, mEventHandlerId ); mEventHandlerId, RsEventType::GXS_CHANGES );
} }
RsGxsUpdateBroadcast::~RsGxsUpdateBroadcast() RsGxsUpdateBroadcast::~RsGxsUpdateBroadcast()