RTBKit  0.9
Open-source framework to create real-time ad bidding systems.
soa/sigslot/signal.cc
00001 /* signal.cc
00002    Jeremy Barnes, 15 November 2010
00003    Copyright (c) 2010 Datacratic.  All rights reserved.
00004    
00005    Code to deal with notifiers.
00006 */
00007 
00008 #include "signal.h"
00009 #include "jml/utils/pair_utils.h"
00010 #include "v8.h"
00011 #include "soa/js/js_utils.h"
00012 #include "soa/jsoncpp/json.h"
00013 
00014 using namespace std;
00015 using namespace ML;
00016 
00017 
00018 namespace Datacratic {
00019 
00020 /*****************************************************************************/
00021 /* SIGNAL INFO                                                               */
00022 /*****************************************************************************/
00023 
00024 Json::Value
00025 SignalInfo::
00026 toJson() const
00027 {
00028     Json::Value result;
00029     result["name"] = eventName;
00030     result["callbackType"] = ML::demangle(*callbackType);
00031     result["objectType"]   = ML::demangle(*objectType);
00032     result["inherited"]    = inherited;
00033     return result;
00034 }
00035 
00036 
00037 /*****************************************************************************/
00038 /* SIGNAL REGISTRY BASE                                                      */
00039 /*****************************************************************************/
00040 
00041 SignalRegistryBase::
00042 SignalRegistryBase()
00043 {
00044 }
00045 
00046 SignalRegistryBase::
00047 SignalRegistryBase(SignalRegistryBase & inheritFrom)
00048 {
00049     inheritSignals(inheritFrom);
00050 }
00051 
00052 SignalRegistryBase::
00053 ~SignalRegistryBase()
00054 {
00055     std::for_each(parentRegistrations.begin(), parentRegistrations.end(),
00056                   [&] (boost::signals2::connection & conn)
00057                   { conn.disconnect(); });
00058 }
00059 
00060 std::vector<std::string>
00061 SignalRegistryBase::
00062 names() const
00063 {
00064     return vector<string>(ML::first_extractor(signals.begin()),
00065                           ML::first_extractor(signals.end()));
00066 }
00067 
00068 SignalInfo
00069 SignalRegistryBase::
00070 info(const std::string & name) const
00071 {
00072     auto it = signals.find(name);
00073     if (it == signals.end())
00074         throw Exception("no signal by name of " + name);
00075     return it->second;
00076 }
00077 
00078 SlotDisconnector
00079 SignalRegistryBase::
00080 doOn(const std::string & name,
00081      void * object,
00082      const std::type_info & objectType,
00083      const Slot & slot,
00084      int priority) const
00085 {
00086     auto it = signals.find(name);
00087     if (it == signals.end())
00088         throw ML::Exception("no signal " + name);
00089     return it->second.registerFn(object, objectType, name, slot, priority, 0);
00090 }
00091 
00092 void
00093 SignalRegistryBase::
00094 inheritSignals(SignalRegistryBase & inheritFrom)
00095 {
00096     for (auto it = inheritFrom.signals.begin(),
00097              end = inheritFrom.signals.end();
00098          it != end;  ++it)
00099         addSignal(it->second, true /* inherited */);
00100     
00101     parentRegistrations.push_back
00102         (inheritFrom.newEvent.connect
00103          (boost::bind(&SignalRegistryBase::addSignal, this, _2, true)));
00104 }
00105 
00106 void
00107 SignalRegistryBase::
00108 add(const std::string & eventName,
00109     //const std::string & description, // TODO: would be nice...
00110     const std::type_info & callbackType,
00111     const std::type_info & objectType,
00112     RegisterFn registerFn, void * data)
00113 {
00114     Info info;
00115     info.eventName = eventName;
00116     info.callbackType = &callbackType;
00117     info.objectType = &objectType;
00118     info.registerFn = registerFn;
00119     info.data = data;
00120     info.inherited = false;
00121     
00122     addSignal(info, false /* inherited */);
00123 }
00124 
00125 void
00126 SignalRegistryBase::
00127 addSignal(const Info & signal, bool inherited)
00128 {
00129     std::string name = signal.eventName;
00130     bool exists = signals.count(name);
00131     Info & info = signals[name];
00132     
00133     if (exists) {
00134         if (info.inherited && inherited)
00135             throw ML::Exception("signal " + signal.eventName
00136                                 + " was inherited twice");
00137 
00138         if (!info.inherited && !inherited)
00139             throw ML::Exception("signal " + signal.eventName
00140                                 + " was added twice");
00141         
00142         if (info.callbackType != signal.callbackType)
00143             throw ML::Exception("signal " + signal.eventName
00144                                 + " had inherited callback type "
00145                                 + ML::demangle(*signal.callbackType)
00146                                 + " but local callback type "
00147                                 + ML::demangle(*info.callbackType));
00148         
00149         // The inherited version shouldn't override our local version
00150         if (!info.inherited && inherited)
00151             return;  
00152     }
00153     
00154     info = signal;
00155     info.inherited = inherited;
00156     
00157     // Notify anything that needs to know that we have a new event
00158     newEvent(*this, info);
00159 }
00160 
00161 } // namespace Datacratic
 All Classes Namespaces Functions Variables Typedefs Enumerations Enumerator