00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00057 #ifndef CONTROL_COMMAND_REGISTRY_H
00058 #define CONTROL_COMMAND_REGISTRY_H
00059
00060
00061 #include "lib/error.hpp"
00062 #include "lib/singleton.hpp"
00063 #include "lib/sync.hpp"
00064 #include "lib/format.hpp"
00065 #include "include/logging.h"
00066 #include "lib/util.hpp"
00067
00068 #include "proc/control/command.hpp"
00069 #include "proc/control/command-signature.hpp"
00070 #include "proc/control/command-argument-holder.hpp"
00071 #include "lib/typed-allocation-manager.hpp"
00072
00073 #include <boost/functional/hash.hpp>
00074 #include <boost/noncopyable.hpp>
00075 #include <tr1/unordered_map>
00076 #include <tr1/memory>
00077 #include <string>
00078 #include <map>
00079
00080
00081
00082 namespace control {
00083
00084 using boost::hash;
00085 using boost::noncopyable;
00086 using std::tr1::shared_ptr;
00087 using std::tr1::unordered_map;
00088 using lib::TypedAllocationManager;
00089 using util::getValue_or_default;
00090 using util::contains;
00091 using std::string;
00092 using std::map;
00093
00094
00101 struct order_by_impl
00102 {
00103 bool
00104 operator() (const Command *pC1, const Command *pC2) const
00105 {
00106 return (!pC1 && pC2)
00107 || ( pC1 && pC2 && (*pC1 < *pC2));
00108 }
00109 };
00110
00111
00119 class CommandRegistry
00120 : public lib::Sync<>
00121 , noncopyable
00122 {
00123
00124 typedef unordered_map<Symbol, Command, hash<Symbol> > CmdIndex;
00125 typedef map< const Command*, Symbol, order_by_impl> ReverseIndex;
00126
00127 TypedAllocationManager allocator_;
00128 CmdIndex index_;
00129 ReverseIndex ridx_;
00130
00131
00132 public:
00133 static lib::Singleton<CommandRegistry> instance;
00134
00135
00136 ~CommandRegistry()
00137 {
00138 INFO (command, "Shutting down Command system...");
00140 ridx_.clear();
00141 index_.clear();
00142 }
00143
00144
00145
00149 void
00150 track (Symbol cmdID, Command const& commandHandle)
00151 {
00152 Lock sync(this);
00153
00154 REQUIRE (commandHandle);
00155 if (contains (index_,cmdID) || contains(ridx_, &commandHandle))
00156 commandHandle.duplicate_detected(cmdID);
00157
00158 Command& indexSlot = index_[cmdID];
00159 indexSlot = commandHandle;
00160 ridx_[&indexSlot] = cmdID;
00161
00162 ENSURE (contains(ridx_, &indexSlot));
00163 ENSURE (contains(index_, cmdID));
00164 }
00165
00166
00171 bool
00172 remove (Symbol cmdID)
00173 {
00174 Lock sync(this);
00175
00176 bool actually_remove = contains (index_,cmdID);
00177 if (actually_remove)
00178 {
00179 ridx_.erase(& index_[cmdID]);
00180 index_.erase(cmdID);
00181 }
00182 ENSURE (!contains (index_,cmdID));
00183 return actually_remove;
00184 }
00185
00186
00190 Command
00191 queryIndex (Symbol cmdID)
00192 {
00193 Lock sync(this);
00194 return getValue_or_default (index_, cmdID, Command() );
00195 }
00196
00197
00202 Symbol
00203 findDefinition (Command const& cmdInstance) const
00204 {
00205 Lock sync(this);
00206 return getValue_or_default (ridx_, &cmdInstance, 0 );
00207 }
00208
00209
00210 size_t
00211 index_size() const
00212 {
00213 return index_.size();
00214 }
00215
00216
00217 size_t
00218 instance_count() const
00219 {
00220 return allocator_.numSlots<CommandImpl>();
00221 }
00222
00223
00229 template< typename SIG_OPER
00230 , typename SIG_CAPT
00231 , typename SIG_UNDO
00232 >
00233 shared_ptr<CommandImpl>
00234 newCommandImpl (function<SIG_OPER>& operFunctor
00235 ,function<SIG_CAPT>& captFunctor
00236 ,function<SIG_UNDO>& undoFunctor)
00237 {
00238
00239
00240
00241 typedef typename UndoSignature<SIG_CAPT>::Memento Mem;
00242 typedef ArgumentHolder<SIG_OPER,Mem> Arguments;
00243
00244 shared_ptr<Arguments> pArg (allocator_.create<Arguments>());
00245
00246 return allocator_.create<CommandImpl> (pArg, operFunctor,captFunctor,undoFunctor);
00247 }
00248
00249
00250
00251
00265 shared_ptr<CommandImpl>
00266 createCloneImpl (CommandImpl const& refObject);
00267
00268
00269 };
00270
00271
00272 }
00273 #endif