/************************************************************* * @brief Destructor *************************************************************/ Connection::~Connection() { // Delete all callback objects CallbackMapIter mapIter = m_CallbackMap.begin() ; while (mapIter != m_CallbackMap.end()) { //char const* pType = mapIter->first ; CallbackList* pList = mapIter->second ; // Delete all callbacks in this list CallbackListIter iter = pList->begin() ; while (iter != pList->end()) { Callback* pCallback = *iter ; iter++ ; delete pCallback ; } mapIter++ ; // Delete the list itself delete pList ; } // Clear out any messages sitting on the queues while (m_IncomingMessageQueue.size() > 0) { ElementXML_Handle hMsg = m_IncomingMessageQueue.back() ; delete hMsg ; m_IncomingMessageQueue.pop() ; } }
static void do_callback_by_id(Fl_Window *win, unsigned int id) { /* FIXME: lock this somehow */ CallbackListIt it = callback_list.begin(), it_end = callback_list.end(); ForeignCallbackInfo *info; for(; it != it_end; ++it) { info = &(*it); /* call it */ if(id == info->hash_id && info->cb) info->cb(win, info->data); } }
void foreign_callback_remove(ForeignCallback cb) { if(callback_list.empty()) return; /* FIXME: lock this somehow */ CallbackListIt it = callback_list.begin(), it_end = callback_list.end(); while(it != it_end) { if((*it).cb == cb) it = callback_list.erase(it); else ++it; } }
/************************************************************* * @brief Removes a callback from the list of callbacks for a particular type of incoming message. * * @param callback The function that was previously registered. If NULL removes all callbacks for this type of message. * @param pType The type of message to unregister from (currently one of "call", "response" or "notify"). * * @returns 0 if successful, otherwise an error code to indicate what went wrong. *************************************************************/ void Connection::UnregisterCallback(IncomingCallback callback, char const* pType) { ClearError() ; if (pType == NULL) { SetError(Error::kInvalidArgument) ; return ; } // See if we have a list of callbacks for this type CallbackList* pList = GetCallbackList(pType) ; if (pList == NULL) { SetError(Error::kCallbackNotFound) ; return ; } if (callback == NULL) { // Caller asked to delete all callbacks for this type delete pList ; m_CallbackMap[pType] = NULL ; return ; } // Walk the list of callbacks, deleting any objects that // match the callback function CallbackListIter iter = pList->begin() ; bool found = false ; while (iter != pList->end()) { Callback* pCallback = *iter ; iter++ ; // See if this function matches the one we were passed // In which case, delete it. if (pCallback->getFunction() == callback) { delete pCallback ; found = true ; } } if (!found) SetError(Error::kCallbackNotFound) ; }
void MessageService::publish(std::string message, StringMap params) { comsSem.wait(); SubscriptionMap::const_iterator got = subscriptions.find(message); if(got != subscriptions.end()) { CallbackList messageList = got->second; for(CallbackList::size_type i = 0; i < messageList.size(); i++) { messageList[i](params); } } comsSem.signal(); }
void signal_emit(Signal *sig, ...) { va_list args; va_start(args, sig); int res; CallbackList *iter = sig->callbacks; while(iter != NULL) { res = iter->data(iter->user_arg, args); iter = iter->next; } va_end(args); sig->emit_counter++; }
void MessageService::subscribe(const std::string& message, Callback callback) { comsSem.wait(); SubscriptionMap::const_iterator got = subscriptions.find(message); if(got == subscriptions.end()) { CallbackList newList; newList.push_back(callback); subscriptions.insert({message, newList}); } else { CallbackList messageList = got->second; messageList.push_back(callback); } comsSem.signal(); }
/************************************************************* * @brief Register a callback for a particular type of incoming message. * * Messages are currently one of: * "call", "response" or "notify" * A call is always paired to a response (think of this as a remote function call that returns a value) * while a notify does not receive a response (think of this as a remote function call that does not return a value). * This type is stored in the "doctype" attribute of the top level SML node in the message. * NOTE: doctype's are case sensitive. * * You MUST register a callback for the "call" type of message. This callback must return a "response" message which is then * sent back over the connection. Other callbacks should not return a message. * Once the returned message has been sent it will be deleted. * * We will maintain a list of callbacks for a given type of SML document and call each in turn. * Each callback on the list will be called in turn until one returns a non-NULL response. No further callbacks * will be called for that message. This ensures that only one response is sent to a message. * * @param callback The function to call when an incoming message is received (of the right type) * @param pUserData This data is passed to the callback. It allows the callback to have some context to work in. Can be NULL. * @param pType The type of message to register for (currently one of "call", "response" or "notify"). * @param addToEnd If true add the callback to the end of the list (called last). If false, add to front where it will be called first. * * @returns 0 if successful, otherwise an error code to indicate what went wrong. *************************************************************/ void Connection::RegisterCallback(IncomingCallback callback, void* pUserData, char const* pType, bool addToEnd) { ClearError() ; if (callback == NULL || pType == NULL) { SetError(Error::kInvalidArgument) ; return ; } // Create the callback object to be stored in the map Callback* pCallback = new Callback(this, callback, pUserData) ; CallbackList* pList = NULL ; // CallbackList* pList = m_CallbackMap[pType] ; // See if we have a list of callbacks for this type yet CallbackMapIter iter = m_CallbackMap.find(pType) ; if (iter != m_CallbackMap.end()) { // If the list already exists, just grab it pList = iter->second ; } else { // Need to create the list pList = new CallbackList() ; m_CallbackMap[pType] = pList ; } // Add the callback to the list if (addToEnd) pList->push_back(pCallback) ; else pList->push_front(pCallback) ; }
static inline void clear_all() { routine_tid = 0; cmdSRSPCallbackPtr.reset( NULL ); cmdCbTmpList.clear(); callbackParserTable.clear(); genCbList.clear(); genCbTmpList.clear(); genBroadcastCbList.clear(); thisDev.reset( NULL ); zigbeeSrvSet.clear(); zigbeeDevSet.clear(); // zigbeeCandDevSet.clear(); }
void foreign_callback_add(Fl_Window *win, const char *id, ForeignCallback cb, void *data) { fl_open_display(); init_foreign_callback_atom_once(); /* remove it if exists */ foreign_callback_remove(cb); ForeignCallbackInfo fc; fc.hash_id = str_hash(id); fc.cb = cb; fc.data = data; /* FIXME: lock this somehow */ callback_list.push_back(fc); /* * Assure the same handler is not added twice since FLTK keeps internal static list of known * handlers per application instance. */ Fl::remove_handler(xevent_handler); Fl::add_handler(xevent_handler); }
bool CallbackMainDispatcher::unregisterCallback(int callbackId) { CallbackList newEventList; { TelldusCore::MutexLocker locker(&d->mutex); for(CallbackList::iterator callback_it = d->callbackList.begin(); callback_it != d->callbackList.end(); ++callback_it) { if ( (*callback_it)->id != callbackId ) { continue; } newEventList.splice(newEventList.begin(), d->callbackList, callback_it); break; } } if (newEventList.size()) { CallbackList::iterator it = newEventList.begin(); { //Lock and unlock to make sure no one else uses the object TelldusCore::MutexLocker locker( &(*it)->mutex ); } delete (*it); newEventList.erase(it); return true; } return false; }
/************************************************************* * @brief Invoke the list of callbacks matching the doctype of the incoming message. * * @param pIncomingMsg The SML message that should be passed to the callbacks. * @returns The response message (or NULL if there is no response from any callback). *************************************************************/ ElementXML* Connection::InvokeCallbacks(ElementXML *pIncomingMsg) { ClearError() ; MessageSML *pIncomingSML = (MessageSML*)pIncomingMsg ; // MessageSML is a soarxml::ElementXML, not sml::ElementXML // Check that we were passed a valid message. if (pIncomingMsg == NULL) { SetError(Error::kInvalidArgument) ; return NULL ; } // Retrieve the type of this message char const* pType = pIncomingSML->GetDocType() ; // Check that this message has a valid doc type (all valid SML do) if (pType == NULL) { SetError(Error::kNoDocType) ; return NULL ; } // Decide if this message is a "call" which requires a "response" bool isIncomingCall = pIncomingSML->IsCall() ; // See if we have a list of callbacks for this type CallbackList* pList = GetCallbackList(pType) ; // Nobody was interested in this type of message, so we're done. if (pList == NULL) { return NULL ; } CallbackListIter iter = pList->begin() ; // Walk the list of callbacks in turn until we reach // the end or one returns a message. while (iter != pList->end()) { Callback* pCallback = *iter ; iter++ ; ElementXML* pResponse = pCallback->Invoke(pIncomingMsg) ; if (pResponse != NULL) { if (isIncomingCall) return pResponse ; // This callback was not for a call and should not return a result. // Delete the result and ignore it. pResponse->ReleaseRefOnHandle() ; pResponse = NULL ; } } // If this is a call, we must respond if (isIncomingCall) SetError(Error::kNoResponseToCall) ; // Nobody returned a response return NULL ; }