mirror of
https://github.com/RetroShare/RetroShare.git
synced 2025-05-05 07:35:12 -04:00
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:
parent
ce5f5faa97
commit
4c0baa1ec3
17 changed files with 165 additions and 139 deletions
|
@ -108,14 +108,6 @@ p3discovery2::p3discovery2(
|
|||
|
||||
// Add self into PGP FriendList.
|
||||
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;
|
||||
}
|
||||
|
||||
void p3discovery2::rsEventsHandler(const RsEvent& event)
|
||||
{
|
||||
Dbg3() << __PRETTY_FUNCTION__ << " " << static_cast<uint32_t>(event.mType) << std::endl;
|
||||
}
|
||||
|
||||
|
||||
/*************************************************************************************/
|
||||
/* AuthGPGService */
|
||||
|
|
|
@ -352,7 +352,7 @@ JsonApiServer::JsonApiServer(): configMutex("JsonApiServer config"),
|
|||
rsEvents, "rsEvents", cAns, session ) )
|
||||
return;
|
||||
|
||||
RsEventType eventType = RsEventType::NONE;
|
||||
RsEventType eventType = RsEventType::__NONE;
|
||||
|
||||
// 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);
|
||||
|
|
|
@ -50,7 +50,7 @@ extern RsEvents* rsEvents;
|
|||
*/
|
||||
enum class RsEventType : uint32_t
|
||||
{
|
||||
NONE = 0, /// Used to detect uninitialized event
|
||||
__NONE = 0, /// Used internally to detect invalid event type passed
|
||||
|
||||
/// @see RsBroadcastDiscovery
|
||||
BROADCAST_DISCOVERY = 1,
|
||||
|
@ -64,7 +64,7 @@ enum class RsEventType : uint32_t
|
|||
/// @see pqissl
|
||||
PEER_CONNECTION = 4,
|
||||
|
||||
/// @see RsGxsChanges // this one is used in RsGxsBroadcast
|
||||
/// @see RsGxsChanges, used also in @see RsGxsBroadcast
|
||||
GXS_CHANGES = 5,
|
||||
|
||||
/// Emitted when a peer state changes, @see RsPeers
|
||||
|
@ -95,9 +95,9 @@ enum class RsEventType : uint32_t
|
|||
FILE_TRANSFER = 14,
|
||||
|
||||
/// @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
|
||||
{
|
||||
protected:
|
||||
RsEvent(RsEventType type) :
|
||||
explicit RsEvent(RsEventType type) :
|
||||
mType(type), mTimePoint(std::chrono::system_clock::now()) {}
|
||||
|
||||
RsEvent() = delete;
|
||||
|
@ -174,8 +174,9 @@ public:
|
|||
* @brief Register events handler
|
||||
* Every time an event is dispatced the registered events handlers will get
|
||||
* 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}
|
||||
* @param eventType Type of event for which the callback is called
|
||||
* @param multiCallback Function that will be called each time an event
|
||||
* is dispatched.
|
||||
* @param[inout] hId Optional storage for handler id, useful to
|
||||
|
@ -183,13 +184,15 @@ public:
|
|||
* value may be provided to the function call but
|
||||
* must habe been generated with
|
||||
* @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.
|
||||
*/
|
||||
virtual bool registerEventsHandler(
|
||||
RsEventType eventType,
|
||||
std::function<void(std::shared_ptr<const RsEvent>)> multiCallback,
|
||||
RsEventsHandlerId_t& hId = RS_DEFAULT_STORAGE_PARAM(RsEventsHandlerId_t, 0)
|
||||
) = 0;
|
||||
RsEventsHandlerId_t& hId = RS_DEFAULT_STORAGE_PARAM(RsEventsHandlerId_t, 0),
|
||||
RsEventType eventType = RsEventType::__NONE ) = 0;
|
||||
|
||||
/**
|
||||
* @brief Unregister event handler
|
||||
|
@ -200,4 +203,3 @@ public:
|
|||
|
||||
virtual ~RsEvents();
|
||||
};
|
||||
|
||||
|
|
|
@ -39,7 +39,7 @@ bool isEventValid(
|
|||
return false;
|
||||
}
|
||||
|
||||
if(event->mType <= RsEventType::NONE)
|
||||
if(event->mType <= RsEventType::__NONE)
|
||||
{
|
||||
errorMessage = "Event has type NONE: " +
|
||||
std::to_string(
|
||||
|
@ -48,9 +48,9 @@ bool isEventValid(
|
|||
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(
|
||||
static_cast<std::underlying_type<RsEventType>::type >(
|
||||
event->mType ) );
|
||||
|
@ -100,25 +100,30 @@ RsEventsHandlerId_t RsEventsService::generateUniqueHandlerId_unlocked()
|
|||
}
|
||||
|
||||
bool RsEventsService::registerEventsHandler(
|
||||
RsEventType eventType,
|
||||
std::function<void(std::shared_ptr<const RsEvent>)> multiCallback,
|
||||
RsEventsHandlerId_t& hId )
|
||||
RsEventsHandlerId_t& hId, RsEventType eventType )
|
||||
{
|
||||
RS_STACK_MUTEX(mHandlerMapMtx);
|
||||
|
||||
if( (int)eventType > mHandlerMaps.size() + 10)
|
||||
{
|
||||
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;
|
||||
return false;
|
||||
}
|
||||
if( eventType >= RsEventType::__MAX)
|
||||
{
|
||||
RsErr() << __PRETTY_FUNCTION__ << " Invalid event type: "
|
||||
<< static_cast<uint32_t>(eventType) << " >= RsEventType::__MAX:"
|
||||
<< static_cast<uint32_t>(RsEventType::__MAX) << std::endl;
|
||||
print_stacktrace();
|
||||
return false;
|
||||
}
|
||||
|
||||
if( (int)eventType >= mHandlerMaps.size())
|
||||
mHandlerMaps.resize( (int)eventType +1 );
|
||||
if(!hId) hId = generateUniqueHandlerId_unlocked();
|
||||
else if (hId > mLastHandlerId)
|
||||
{
|
||||
RsErr() << __PRETTY_FUNCTION__ << " Invalid handler id: " << hId
|
||||
<< " how did you generate it? " << std::endl;
|
||||
print_stacktrace();
|
||||
return false;
|
||||
}
|
||||
|
||||
if(!hId)
|
||||
hId = generateUniqueHandlerId_unlocked();
|
||||
|
||||
mHandlerMaps[(int)eventType][hId] = multiCallback;
|
||||
mHandlerMaps[static_cast<std::size_t>(eventType)][hId] = multiCallback;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -126,14 +131,14 @@ bool RsEventsService::unregisterEventsHandler(RsEventsHandlerId_t hId)
|
|||
{
|
||||
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);
|
||||
if(it != mHandlerMaps[i].end())
|
||||
{
|
||||
{
|
||||
mHandlerMaps[i].erase(it);
|
||||
return true;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
@ -174,27 +179,29 @@ dispatchEventFromQueueLock:
|
|||
|
||||
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)
|
||||
{
|
||||
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
|
||||
for(auto cbit: mHandlerMaps[event_type_index]) cbit.second(event);
|
||||
|
||||
// Call all clients that registered a callback for this event type
|
||||
|
||||
for(auto cbit: mHandlerMaps[event_type_index])
|
||||
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);
|
||||
/* 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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,7 +3,8 @@
|
|||
* *
|
||||
* 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 *
|
||||
* it under the terms of the GNU Lesser General Public License as *
|
||||
|
@ -24,6 +25,7 @@
|
|||
#include <memory>
|
||||
#include <cstdint>
|
||||
#include <deque>
|
||||
#include <array>
|
||||
|
||||
#include "retroshare/rsevents.h"
|
||||
#include "util/rsthreads.h"
|
||||
|
@ -35,7 +37,6 @@ class RsEventsService :
|
|||
public:
|
||||
RsEventsService():
|
||||
mHandlerMapMtx("RsEventsService::mHandlerMapMtx"), mLastHandlerId(1),
|
||||
mHandlerMaps(static_cast<int>(RsEventType::MAX)),
|
||||
mEventQueueMtx("RsEventsService::mEventQueueMtx") {}
|
||||
|
||||
/// @see RsEvents
|
||||
|
@ -55,10 +56,9 @@ public:
|
|||
|
||||
/// @see RsEvents
|
||||
bool registerEventsHandler(
|
||||
RsEventType eventType,
|
||||
std::function<void(std::shared_ptr<const RsEvent>)> multiCallback,
|
||||
RsEventsHandlerId_t& hId = RS_DEFAULT_STORAGE_PARAM(RsEventsHandlerId_t, 0)
|
||||
) override;
|
||||
RsEventsHandlerId_t& hId = RS_DEFAULT_STORAGE_PARAM(RsEventsHandlerId_t, 0),
|
||||
RsEventType eventType = RsEventType::__NONE ) override;
|
||||
|
||||
/// @see RsEvents
|
||||
bool unregisterEventsHandler(RsEventsHandlerId_t hId) override;
|
||||
|
@ -67,10 +67,12 @@ protected:
|
|||
RsMutex mHandlerMapMtx;
|
||||
RsEventsHandlerId_t mLastHandlerId;
|
||||
|
||||
std::vector<
|
||||
std::map<
|
||||
RsEventsHandlerId_t,
|
||||
std::function<void(std::shared_ptr<const RsEvent>)> > > mHandlerMaps;
|
||||
std::array<
|
||||
std::map<
|
||||
RsEventsHandlerId_t,
|
||||
std::function<void(std::shared_ptr<const RsEvent>)> >,
|
||||
static_cast<std::size_t>(RsEventType::__MAX)
|
||||
> mHandlerMaps;
|
||||
|
||||
RsMutex mEventQueueMtx;
|
||||
std::deque< std::shared_ptr<const RsEvent> > mEventQueue;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue