Changeset 1255
- Timestamp:
- May 12, 2008, 2:50:21 PM (17 years ago)
- Location:
- code/branches/console/src/core
- Files:
-
- 7 edited
Legend:
- Unmodified
- Added
- Removed
-
code/branches/console/src/core/CommandExecutor.cc
r1230 r1255 48 48 ConsoleCommandShortcutGeneric(keyword3, createExecutor((FunctorStatic*)0, "bind", AccessLevel::User)); 49 49 50 ConsoleCommandShortcutExtern( exec, AccessLevel::None);50 ConsoleCommandShortcutExtern(source, AccessLevel::None); 51 51 ConsoleCommandShortcutExtern(echo, AccessLevel::None); 52 52 ConsoleCommandShortcutExtern(puts, AccessLevel::None); … … 56 56 ConsoleCommandShortcutExtern(write, AccessLevel::None); 57 57 58 void exec(const std::string& filename)58 void source(const std::string& filename) 59 59 { 60 60 static std::set<std::string> executingFiles; … … 63 63 if (it != executingFiles.end()) 64 64 { 65 COUT(1) << "Error: Recurring execcommand in \"" << filename << "\". Stopped execution." << std::endl;65 COUT(1) << "Error: Recurring source command in \"" << filename << "\". Stopped execution." << std::endl; 66 66 return; 67 67 } … … 73 73 if (!file.is_open()) 74 74 { 75 COUT(1) << "Error: Couldn't executefile \"" << filename << "\"." << std::endl;75 COUT(1) << "Error: Couldn't open file \"" << filename << "\"." << std::endl; 76 76 return; 77 77 } -
code/branches/console/src/core/CommandExecutor.h
r1230 r1255 63 63 }; 64 64 65 void exec(const std::string& filename);65 void source(const std::string& filename); 66 66 std::string echo(const std::string& text); 67 67 void puts(bool newline, const std::string& test); -
code/branches/console/src/core/Script.cc
r1115 r1255 67 67 { 68 68 output_ += str; 69 COUT(4) << "Lua_output!:" << std::endl << str << std::endl << "***" << std::endl; 69 // COUT(4) << "Lua_output!:" << std::endl << str << std::endl << "***" << std::endl; 70 COUT(5) << str << std::endl; 70 71 } 71 72 … … 99 100 100 101 if (luaTags) luaSource_ = replaceLuaTags(levelString); 101 COUT( 4) << "ParsedSourceCode: " << luaSource_ << std::endl;102 COUT(5) << "ParsedSourceCode: " << luaSource_ << std::endl; 102 103 } 103 104 -
code/branches/console/src/core/TclBind.cc
r1247 r1255 33 33 #include "CommandExecutor.h" 34 34 #include "Debug.h" 35 #include "TclThreadManager.h" 35 36 #include "TclBind.h" 36 37 … … 70 71 { 71 72 this->interpreter_ = new Tcl::interpreter(this->tclLibPath_); 72 this->interpreter_->def("orxonox", TclBind::tcl_orxonox, Tcl::variadic()); 73 this->interpreter_->def("orxonox::query", TclBind::tcl_query, Tcl::variadic()); 74 this->interpreter_->def("orxonox::crossquery", TclThreadManager::tcl_crossquery, Tcl::variadic()); 73 75 this->interpreter_->def("execute", TclBind::tcl_execute, Tcl::variadic()); 74 this->interpreter_->eval("rename exit tclexit; proc exit {} { orxonox exit }"); 75 this->interpreter_->eval("redef_puts"); 76 77 try 78 { 79 this->interpreter_->eval("proc query args { orxonox::query $args }"); 80 this->interpreter_->eval("proc crossquery {id args} { orxonox::crossquery 0 $id $args }"); 81 this->interpreter_->eval("set id 0"); 82 this->interpreter_->eval("rename exit tcl::exit; proc exit {} { execute exit }"); 83 this->interpreter_->eval("redef_puts"); 84 } 85 catch (Tcl::tcl_error const &e) 86 { COUT(1) << "Tcl error while creating Tcl-interpreter: " << e.what() << std::endl; } 87 catch (std::exception const &e) 88 { COUT(1) << "Error while creating Tcl-interpreter: " << e.what() << std::endl; } 76 89 } 77 90 } … … 88 101 } 89 102 90 void TclBind::tcl_puts(Tcl::object const &args)103 std::string TclBind::tcl_query(Tcl::object const &args) 91 104 { 92 COUT(0) << args.get() << std::endl; 93 } 94 95 std::string TclBind::tcl_orxonox(Tcl::object const &args) 96 { 97 std::cout << "Tcl_orxonox: args: " << args.get() << std::endl; 105 std::cout << "Tcl_query: args: " << args.get() << std::endl; 98 106 std::string command = args.get(); 99 107 100 if(command.size() >= 2 && command[0] == '{' && command[command.size() - 1] == '}')108 while (command.size() >= 2 && command[0] == '{' && command[command.size() - 1] == '}') 101 109 command = command.substr(1, command.size() - 2); 102 110 … … 115 123 std::string command = args.get(); 116 124 117 if(command.size() >= 2 && command[0] == '{' && command[command.size() - 1] == '}')125 while (command.size() >= 2 && command[0] == '{' && command[command.size() - 1] == '}') 118 126 command = command.substr(1, command.size() - 2); 119 127 … … 132 140 } 133 141 catch (Tcl::tcl_error const &e) 134 { 135 COUT(1) << "tcl> Error: " << e.what() << std::endl; 136 } 142 { COUT(1) << "tcl> Error: " << e.what() << std::endl; } 137 143 catch (std::exception const &e) 138 { 139 COUT(1) << "Error while executing Tcl: " << e.what() << std::endl; 140 } 144 { COUT(1) << "Error while executing Tcl: " << e.what() << std::endl; } 141 145 142 146 return ""; … … 151 155 } 152 156 catch (Tcl::tcl_error const &e) 153 { 154 COUT(1) << "Tcl error: " << e.what() << std::endl; 155 } 157 { COUT(1) << "Tcl error: " << e.what() << std::endl; } 156 158 catch (std::exception const &e) 157 { 158 COUT(1) << "Error while executing Tcl: " << e.what() << std::endl; 159 } 159 { COUT(1) << "Error while executing Tcl: " << e.what() << std::endl; } 160 160 161 161 return false; -
code/branches/console/src/core/TclBind.h
r1230 r1255 47 47 void createTclInterpreter(); 48 48 void createNewTclInterpreter(); 49 Tcl::interpreter* getTclInterpreter() const { return this->interpreter_; } 49 50 50 static void tcl_puts(Tcl::object const &args); 51 51 static std::string tcl_query(Tcl::object const &args); 52 52 static void tcl_execute(Tcl::object const &args); 53 static std::string tcl_orxonox(Tcl::object const &args);54 53 55 54 static bool eval(const std::string& tclcode); -
code/branches/console/src/core/TclThreadManager.cc
r1247 r1255 43 43 #include "util/Convert.h" 44 44 45 #define TCLTHREAD _MAX_QUEUE_LENGTH 102446 #define TCLTHREAD _MAX_CPU_USAGE 0.5045 #define TCLTHREADMANAGER_MAX_QUEUE_LENGTH 1024 46 #define TCLTHREADMANAGER_MAX_CPU_USAGE 0.50 47 47 48 48 namespace orxonox 49 49 { 50 ConsoleCommand(TclThreadManager, tclthread, AccessLevel::None, true);50 // ConsoleCommand(TclThreadManager, tclthread, AccessLevel::None, true); 51 51 ConsoleCommand(TclThreadManager, create, AccessLevel::None, false); 52 52 ConsoleCommand(TclThreadManager, destroy, AccessLevel::None, false); 53 53 ConsoleCommand(TclThreadManager, execute, AccessLevel::None, false); 54 54 ConsoleCommand(TclThreadManager, query, AccessLevel::None, false); 55 ConsoleCommand(TclThreadManager, status, AccessLevel::None, false);56 ConsoleCommand(TclThreadManager, dump, AccessLevel::None, false);55 // ConsoleCommand(TclThreadManager, status, AccessLevel::None, false); 56 // ConsoleCommand(TclThreadManager, dump, AccessLevel::None, false); 57 57 58 58 TclThreadManager* instance = &TclThreadManager::getInstance(); … … 62 62 RegisterRootObject(TclThreadManager); 63 63 64 this->IDcount_ = 0; 65 this->isReady_ = false; 66 this->isQuerying_ = false; 67 this->queryID_ = 0; 64 this->threadCounter_ = 0; 65 this->orxonoxInterpreterBundle_.id_ = 0; 66 this->orxonoxInterpreterBundle_.interpreter_ = TclBind::getInstance().getTclInterpreter(); 68 67 } 69 68 … … 74 73 } 75 74 76 void TclThreadManager::tclthread(unsigned int threadID, const std::string& command)77 {78 TclThreadManager::execute(threadID, command);79 }80 81 75 unsigned int TclThreadManager::create() 82 76 { 83 if (TclThreadManager::getInstance().createTclThread()) 84 { 85 COUT(0) << "Created new Tcl-thread with ID " << TclThreadManager::getInstance().IDcount_ << "." << std::endl; 86 return TclThreadManager::getInstance().IDcount_; 87 } 88 return 0; 77 boost::mutex::scoped_lock lock(TclThreadManager::getInstance().bundlesMutex_); 78 TclThreadManager::getInstance().threadCounter_++; 79 std::string name = getConvertedValue<unsigned int, std::string>(TclThreadManager::getInstance().threadCounter_); 80 81 TclInterpreterBundle* bundle = new TclInterpreterBundle; 82 bundle->id_ = TclThreadManager::getInstance().threadCounter_; 83 bundle->interpreter_ = TclThreadManager::getInstance().createNewTclInterpreter(name); 84 bundle->interpreterName_ = name; 85 bundle->running_ = true; 86 87 TclThreadManager::getInstance().interpreterBundles_[TclThreadManager::getInstance().threadCounter_] = bundle; 88 COUT(0) << "Created new Tcl-interpreter with ID " << TclThreadManager::getInstance().threadCounter_ << std::endl; 89 return TclThreadManager::getInstance().threadCounter_; 89 90 } 90 91 91 92 void TclThreadManager::destroy(unsigned int threadID) 92 93 { 93 if (TclThreadManager::getInstance().destroyTclThread(threadID)) 94 { 95 COUT(0) << "Destroyed Tcl-thread with ID " << threadID << "." << std::endl; 94 TclInterpreterBundle* bundle = TclThreadManager::getInstance().getInterpreterBundle(threadID); 95 if (bundle) 96 { 97 { 98 boost::mutex::scoped_lock lock(bundle->runningMutex_); 99 bundle->running_ = false; 100 } 101 { 102 boost::mutex::scoped_lock lock(bundle->finishedMutex_); 103 while (!bundle->finished_) 104 bundle->finishedCondition_.wait(lock); 105 } 106 { 107 boost::mutex::scoped_lock lock(bundle->interpreterMutex_); 108 delete bundle->interpreter_; 109 } 110 delete bundle; 111 { 112 boost::mutex::scoped_lock lock(TclThreadManager::getInstance().bundlesMutex_); 113 TclThreadManager::getInstance().interpreterBundles_.erase(threadID); 114 } 96 115 } 97 116 } … … 99 118 void TclThreadManager::execute(unsigned int threadID, const std::string& command) 100 119 { 101 TclThreadManager::getInstance().pushCommand Back(threadID, command);120 TclThreadManager::getInstance().pushCommandToQueue(threadID, command); 102 121 } 103 122 104 123 std::string TclThreadManager::query(unsigned int threadID, const std::string& command) 105 124 { 106 return TclThreadManager::getInstance().eval(threadID, command); 107 } 108 109 void TclThreadManager::status() 110 { 111 COUT(0) << "Thread ID" << '\t' << "Queue size" << '\t' << "State" << std::endl; 112 113 std::string output = "Orxonox"; 114 output += "\t\t"; 115 { 116 // mutex orxqueue 117 boost::mutex::scoped_lock lock(TclThreadManager::getInstance().orxonoxQueueMutex_); 118 output += getConvertedValue<unsigned int, std::string>(TclThreadManager::getInstance().orxonoxQueue_.size()); 119 } 120 output += "\t\t"; 121 { 122 // mutex orxstate 123 boost::mutex::scoped_lock lock(TclThreadManager::getInstance().orxonoxStateMutex_); 124 if (TclThreadManager::getInstance().isReady_) 125 output += "ready"; 126 else 127 output += "busy"; 128 } 129 COUT(0) << output << std::endl; 130 131 // mutex threads 132 boost::mutex::scoped_lock lock(TclThreadManager::getInstance().threadsMutex_); 133 for (std::map<unsigned int, TclThread*>::const_iterator it = TclThreadManager::getInstance().threads_.begin(); it != TclThreadManager::getInstance().threads_.end(); ++it) 134 { 135 std::string output = getConvertedValue<unsigned int, std::string>((*it).first); 136 output += "\t\t"; 137 { 138 boost::mutex::scoped_lock lock(TclThreadManager::getInstance().threadQueuesMutex_); 139 std::map<unsigned int, std::pair<std::queue<std::string>, boost::condition*> >::const_iterator it2 = TclThreadManager::getInstance().threadQueues_.find((*it).first); 140 if (it2 != TclThreadManager::getInstance().threadQueues_.end()) 141 output += getConvertedValue<unsigned int, std::string>((*it2).second.first.size()); 142 else 143 output += "-"; 144 } 145 output += "\t\t"; 146 if (TclThreadManager::getInstance().getState((*it).second) == TclThread::Ready) 147 output += "ready"; 148 else 149 output += "busy"; 150 151 COUT(0) << output << std::endl; 152 } 153 } 154 155 void TclThreadManager::dump(unsigned int threadID) 156 { 157 if (threadID == 0) 158 { 159 // mutex orxqueue 160 boost::mutex::scoped_lock lock(TclThreadManager::getInstance().orxonoxQueueMutex_); 161 162 COUT(0) << "Queue dump of Orxonox:" << std::endl; 163 for (unsigned int index = 0; index < TclThreadManager::getInstance().orxonoxQueue_.size(); index++) 164 { 165 std::string command = TclThreadManager::getInstance().orxonoxQueue_.front(); 166 COUT(0) << index << ": " << command << std::endl; 167 TclThreadManager::getInstance().orxonoxQueue_.pop(); 168 TclThreadManager::getInstance().orxonoxQueue_.push(command); 169 } 170 } 171 else 172 { 173 // mutex threadqueues 174 boost::mutex::scoped_lock lock(TclThreadManager::getInstance().threadQueuesMutex_); 175 176 std::map<unsigned int, std::pair<std::queue<std::string>, boost::condition*> >::iterator it = TclThreadManager::getInstance().threadQueues_.find(threadID); 177 if (it != TclThreadManager::getInstance().threadQueues_.end()) 178 { 179 COUT(0) << "Queue dump of Tcl-thread " << threadID << ":" << std::endl; 180 for (unsigned int index = 0; index < (*it).second.first.size(); index++) 181 { 182 std::string command = (*it).second.first.front(); 183 COUT(0) << index << ": " << command << std::endl; 184 (*it).second.first.pop(); 185 (*it).second.first.push(command); 186 } 187 } 188 else 189 { 190 COUT(1) << "Error: (" << __LINE__ << ") No Tcl-thread with ID " << threadID << "." << std::endl; 191 } 192 } 125 return TclThreadManager::getInstance().evalQuery(TclThreadManager::getInstance().orxonoxInterpreterBundle_.id_, threadID, command); 193 126 } 194 127 195 128 void TclThreadManager::tcl_execute(Tcl::object const &args) 196 129 { 197 std::cout << "Tcl-thread_execute: args: " << args.get() << std::endl;198 130 std::string command = args.get(); 199 200 if (command.size() >= 2 && command[0] == '{' && command[command.size() - 1] == '}')201 command = command.substr(1, command.size() - 2);202 203 TclThreadManager::getInstance().pushCommandBack(command);204 }205 206 std::string TclThreadManager::tcl_query(int id, Tcl::object const &args)207 {208 std::cout << "Tcl-thread_query: id: " << id << " args: " << args.get() << std::endl;209 {210 // mutex query211 boost::mutex::scoped_lock lock(TclThreadManager::getInstance().orxonoxQueryMutex_);212 if (TclThreadManager::getInstance().isQuerying_ && (id == (int)TclThreadManager::getInstance().queryID_))213 {214 COUT(1) << "Error: Orxonox Tcl-interpreter can't be queried right now." << std::endl;215 return "";216 }217 }218 219 std::string command = args.get();220 221 131 while (command.size() >= 2 && command[0] == '{' && command[command.size() - 1] == '}') 222 132 command = command.substr(1, command.size() - 2); 223 133 224 return TclThreadManager::getInstance().eval(command); 225 } 226 227 Tcl::interpreter* TclThreadManager::createTclInterpreter(unsigned int threadID) const 134 TclThreadManager::getInstance().pushCommandToQueue(command); 135 } 136 137 std::string TclThreadManager::tcl_query(int querierID, Tcl::object const &args) 138 { 139 std::string command = args.get(); 140 while (command.size() >= 2 && command[0] == '{' && command[command.size() - 1] == '}') 141 command = command.substr(1, command.size() - 2); 142 143 return TclThreadManager::getInstance().evalQuery((unsigned int)querierID, command); 144 } 145 146 std::string TclThreadManager::tcl_crossquery(int querierID, int threadID, Tcl::object const &args) 147 { 148 std::string command = args.get(); 149 while (command.size() >= 2 && command[0] == '{' && command[command.size() - 1] == '}') 150 command = command.substr(1, command.size() - 2); 151 152 return TclThreadManager::getInstance().evalQuery((unsigned int)querierID, (unsigned int)threadID, command); 153 } 154 155 bool TclThreadManager::tcl_running(int threadID) 156 { 157 TclInterpreterBundle* bundle = TclThreadManager::getInstance().getInterpreterBundle((unsigned int)threadID); 158 if (bundle) 159 { 160 boost::mutex::scoped_lock lock(bundle->runningMutex_); 161 return bundle->running_; 162 } 163 return false; 164 } 165 166 Tcl::interpreter* TclThreadManager::createNewTclInterpreter(const std::string& threadID) 228 167 { 229 168 Tcl::interpreter* i = 0; 230 169 i = new Tcl::interpreter(TclBind::getInstance().getTclLibPath()); 231 170 232 i->def("query", TclThreadManager::tcl_query, Tcl::variadic());233 i->def("execute", TclThreadManager::tcl_execute, Tcl::variadic());234 235 std::string id = getConvertedValue<unsigned int, std::string>(threadID);236 171 try 237 172 { 238 i->eval("rename exit tclexit; proc exit {} { orxonox TclThreadManager destroy " + id + " }"); 239 i->eval("proc orxonox args { query " + id + " $args }"); 240 i->eval("set threadid " + id); 173 i->def("orxonox::query", TclThreadManager::tcl_query, Tcl::variadic()); 174 i->def("orxonox::crossquery", TclThreadManager::tcl_crossquery, Tcl::variadic()); 175 i->def("orxonox::execute", TclThreadManager::tcl_execute, Tcl::variadic()); 176 i->def("orxonox::running", TclThreadManager::tcl_running); 177 178 i->def("execute", TclThreadManager::tcl_execute, Tcl::variadic()); 179 i->eval("proc query args { orxonox::query " + threadID + " $args }"); 180 i->eval("proc crossquery {id args} { orxonox::crossquery " + threadID + " $id $args }"); 181 i->eval("set id " + threadID); 182 183 i->eval("rename exit tcl::exit"); 184 i->eval("proc exit {} { orxonox TclThreadManager destroy " + threadID + " }"); 185 241 186 i->eval("redef_puts"); 187 188 i->eval("rename while tcl::while"); 189 i->eval("proc while {test command} { tcl::while {$test && [orxonox::running " + threadID + "]} \"$command\" }"); 190 // i->eval("rename for tcl::for"); 191 // i->eval("proc for {start test next command} { uplevel tcl::for \"$start\" \"$test\" \"$next\" \"$command\" }"); 242 192 } 243 193 catch (Tcl::tcl_error const &e) 244 { 245 COUT(1) << "Tcl error: " << e.what() << std::endl; 246 } 194 { COUT(1) << "Tcl error while creating Tcl-interpreter (" << threadID << "): " << e.what() << std::endl; } 247 195 catch (std::exception const &e) 248 { 249 COUT(1) << "Error while creating Tcl-thread (" << id << "): " << e.what() << std::endl; 250 } 196 { COUT(1) << "Error while creating Tcl-interpreter (" << threadID << "): " << e.what() << std::endl; } 251 197 252 198 return i; 253 199 } 254 200 255 bool TclThreadManager::createTclThread() 256 { 257 this->IDcount_++; 258 TclThread* newthread = new TclThread; 259 newthread->threadID_ = this->IDcount_; 260 newthread->interpreter_ = this->createTclInterpreter(this->IDcount_); 261 newthread->evalMutex_ = new boost::mutex; 262 newthread->stateMutex_ = new boost::mutex; 263 newthread->state_ = new TclThread::State(TclThread::Ready); 264 newthread->thread_ = new boost::thread(boost::bind(&tclThreadLoop, newthread)); 265 { 266 // mutex threads 267 boost::mutex::scoped_lock lock(this->threadsMutex_); 268 this->threads_[this->IDcount_] = newthread; 269 } 270 { 271 // mutes threadqueues 272 boost::mutex::scoped_lock lock(this->threadQueuesMutex_); 273 this->threadQueues_[this->IDcount_] = std::pair<std::queue<std::string>, boost::condition*>(std::queue<std::string>(), new boost::condition()); 201 TclInterpreterBundle* TclThreadManager::getInterpreterBundle(unsigned int threadID) 202 { 203 if (threadID == 0) 204 return &this->orxonoxInterpreterBundle_; 205 206 boost::mutex::scoped_lock lock(this->bundlesMutex_); 207 std::map<unsigned int, TclInterpreterBundle*>::iterator it = this->interpreterBundles_.find(threadID); 208 if (it != this->interpreterBundles_.end()) 209 { 210 return (*it).second; 211 } 212 else 213 { 214 this->forceCommandToFrontOfQueue("error Error: No Tcl-interpreter with ID " + getConvertedValue<unsigned int, std::string>(threadID) + " existing."); 215 return 0; 216 } 217 } 218 219 std::string TclThreadManager::dumpList(const std::list<unsigned int>& list) 220 { 221 std::string output = ""; 222 for (std::list<unsigned int>::const_iterator it = list.begin(); it != list.end(); ++it) 223 { 224 if (it != list.begin()) 225 output += " "; 226 227 output += getConvertedValue<unsigned int, std::string>(*it); 228 } 229 return output; 230 } 231 232 void TclThreadManager::pushCommandToQueue(const std::string& command) 233 { 234 boost::mutex::scoped_lock lock(this->orxonoxInterpreterBundle_.queueMutex_); 235 while (this->orxonoxInterpreterBundle_.queue_.size() >= TCLTHREADMANAGER_MAX_QUEUE_LENGTH) 236 this->fullQueueCondition_.wait(lock); 237 238 this->orxonoxInterpreterBundle_.queue_.push_back(command); 239 } 240 241 void TclThreadManager::forceCommandToFrontOfQueue(const std::string& command) 242 { 243 boost::mutex::scoped_lock lock(this->orxonoxInterpreterBundle_.queueMutex_); 244 this->orxonoxInterpreterBundle_.queue_.push_front(command); 245 } 246 247 std::string TclThreadManager::popCommandFromQueue() 248 { 249 boost::mutex::scoped_lock lock(this->orxonoxInterpreterBundle_.queueMutex_); 250 std::string temp = this->orxonoxInterpreterBundle_.queue_.front(); 251 this->orxonoxInterpreterBundle_.queue_.pop_front(); 252 this->fullQueueCondition_.notify_one(); 253 return temp; 254 } 255 256 bool TclThreadManager::queueIsEmpty() 257 { 258 boost::mutex::scoped_lock lock(this->orxonoxInterpreterBundle_.queueMutex_); 259 return this->orxonoxInterpreterBundle_.queue_.empty(); 260 } 261 262 void TclThreadManager::pushCommandToQueue(unsigned int threadID, const std::string& command) 263 { 264 TclInterpreterBundle* bundle = this->getInterpreterBundle(threadID); 265 if (bundle) 266 { 267 boost::mutex::scoped_lock lock(bundle->queueMutex_); 268 if (bundle->queue_.size() >= TCLTHREADMANAGER_MAX_QUEUE_LENGTH) 269 { 270 this->forceCommandToFrontOfQueue("error Error: Queue of Tcl-interpreter " + getConvertedValue<unsigned int, std::string>(threadID) + " is full, couldn't add command."); 271 return; 272 } 273 274 bundle->queue_.push_back(command); 275 } 276 } 277 278 std::string TclThreadManager::popCommandFromQueue(unsigned int threadID) 279 { 280 TclInterpreterBundle* bundle = this->getInterpreterBundle(threadID); 281 if (bundle) 282 { 283 boost::mutex::scoped_lock lock(bundle->queueMutex_); 284 std::string temp = bundle->queue_.front(); 285 bundle->queue_.pop_front(); 286 return temp; 287 } 288 return ""; 289 } 290 291 bool TclThreadManager::queueIsEmpty(unsigned int threadID) 292 { 293 TclInterpreterBundle* bundle = this->getInterpreterBundle(threadID); 294 if (bundle) 295 { 296 boost::mutex::scoped_lock lock(bundle->queueMutex_); 297 return bundle->queue_.empty(); 274 298 } 275 299 return true; 276 300 } 277 301 278 bool TclThreadManager::destroyTclThread(unsigned int threadID) 279 { 280 // mutex threads 281 boost::mutex::scoped_lock lock(this->threadsMutex_); 282 283 std::map<unsigned int, TclThread*>::iterator it = this->threads_.find(threadID); 284 if (it != this->threads_.end()) 285 { 286 this->setState((*it).second, TclThread::Finished); 287 (*it).second->thread_->timed_join(boost::posix_time::time_duration(0, 0, 0, 10)); 288 289 delete (*it).second->interpreter_; 290 delete (*it).second->thread_; 291 delete (*it).second->evalMutex_; 292 delete (*it).second->stateMutex_; 293 delete (*it).second->state_; 294 delete (*it).second; 295 296 this->threads_.erase(it); 297 { 298 // mutex threadqueues 299 boost::mutex::scoped_lock lock(this->threadQueuesMutex_); 300 std::map<unsigned int, std::pair<std::queue<std::string>, boost::condition*> >::iterator it = this->threadQueues_.find(threadID); 301 if (it != this->threadQueues_.end()) 302 bool TclThreadManager::updateQueriersList(TclInterpreterBundle* querier, TclInterpreterBundle* target) 303 { 304 if (querier == target) 305 return false; 306 307 boost::mutex::scoped_lock lock(target->queriersMutex_); 308 309 { 310 boost::mutex::scoped_lock lock(querier->queriersMutex_); 311 target->queriers_.insert(target->queriers_.end(), querier->queriers_.begin(), querier->queriers_.end()); 312 } 313 314 target->queriers_.insert(target->queriers_.end(), querier->id_); 315 316 if (std::find(target->queriers_.begin(), target->queriers_.end(), target->id_) != target->queriers_.end()) 317 { 318 this->forceCommandToFrontOfQueue("error Error: Circular query (" + this->dumpList(target->queriers_) + " -> " + getConvertedValue<unsigned int, std::string>(target->id_) + "), couldn't query Tcl-interpreter with ID " + getConvertedValue<unsigned int, std::string>(target->id_) + " from other interpreter with ID " + getConvertedValue<unsigned int, std::string>(querier->id_) + "."); 319 return false; 320 } 321 322 return true; 323 } 324 325 std::string TclThreadManager::evalQuery(unsigned int querierID, const std::string& command) 326 { 327 TclInterpreterBundle* querier = this->getInterpreterBundle(querierID); 328 std::string output = ""; 329 if (querier) 330 { 331 if (this->updateQueriersList(querier, &this->orxonoxInterpreterBundle_)) 332 { 333 boost::mutex::scoped_lock lock(this->orxonoxInterpreterBundle_.interpreterMutex_); 334 this->orxonoxEvalCondition_.wait(lock); 335 336 if (!CommandExecutor::execute(command, false)) 337 this->forceCommandToFrontOfQueue("error Error: Can't execute command \"" + command + "\"!"); 338 339 if (CommandExecutor::getLastEvaluation().hasReturnvalue()) 340 output = CommandExecutor::getLastEvaluation().getReturnvalue().toString(); 341 } 342 343 boost::mutex::scoped_lock lock(this->orxonoxInterpreterBundle_.queriersMutex_); 344 this->orxonoxInterpreterBundle_.queriers_.clear(); 345 } 346 return output; 347 } 348 349 std::string TclThreadManager::evalQuery(unsigned int querierID, unsigned int threadID, const std::string& command) 350 { 351 TclInterpreterBundle* target = this->getInterpreterBundle(threadID); 352 std::string output = ""; 353 if (target) 354 { 355 TclInterpreterBundle* querier = 0; 356 if (querierID) 357 querier = this->getInterpreterBundle(querierID); 358 else 359 querier = &this->orxonoxInterpreterBundle_; 360 361 if (querier) 362 { 363 if (this->updateQueriersList(querier, target)) 302 364 { 303 delete (*it).second.second; 304 this->threadQueues_.erase(threadID); 305 } 306 else 307 { 308 return false; 309 } 310 } 311 return true; 312 } 313 else 314 { 315 COUT(1) << "Error: (" << __LINE__ << ") No Tcl-thread with ID " << threadID << "." << std::endl; 316 return false; 317 } 318 } 319 320 void TclThreadManager::setState(TclThread* tclThread, TclThread::State state) 321 { 322 // mutex state 323 boost::mutex::scoped_lock lock(*tclThread->stateMutex_); 324 *tclThread->state_ = state; 325 } 326 327 TclThread::State TclThreadManager::getState(TclThread* tclThread) 328 { 329 // mutex state 330 boost::mutex::scoped_lock lock(*tclThread->stateMutex_); 331 TclThread::State state = *tclThread->state_; 332 return state; 333 } 334 335 void TclThreadManager::pushCommandBack(const std::string& command) 336 { 337 // mutex orxqueue 338 boost::mutex::scoped_lock lock(this->orxonoxQueueMutex_); 339 340 while (this->orxonoxQueue_.size() >= TCLTHREAD_MAX_QUEUE_LENGTH) 341 this->orxonoxQueueCondition_.wait(lock); 342 343 this->orxonoxQueue_.push(command); 344 } 345 346 std::string TclThreadManager::popCommandFront() 347 { 348 // mutex orxqueue 349 boost::mutex::scoped_lock lock(this->orxonoxQueueMutex_); 350 351 std::string command = this->orxonoxQueue_.front(); 352 this->orxonoxQueue_.pop(); 353 354 this->orxonoxQueueCondition_.notify_one(); 355 356 return command; 357 } 358 359 bool TclThreadManager::isEmpty() 360 { 361 // mutex orxqueue 362 boost::mutex::scoped_lock lock(this->orxonoxQueueMutex_); 363 364 return this->orxonoxQueue_.empty(); 365 } 366 367 void TclThreadManager::pushCommandBack(unsigned int threadID, const std::string& command) 368 { 369 // mutex threadqueues 370 boost::mutex::scoped_lock lock(this->threadQueuesMutex_); 371 372 std::map<unsigned int, std::pair<std::queue<std::string>, boost::condition*> >::iterator it = this->threadQueues_.find(threadID); 373 if (it != this->threadQueues_.end()) 374 { 375 while ((*it).second.first.size() >= TCLTHREAD_MAX_QUEUE_LENGTH) 376 (*it).second.second->wait(lock); 377 378 (*it).second.first.push(command); 379 } 380 else 381 { 382 COUT(1) << "Error: (" << __LINE__ << ") No Tcl-thread with ID " << threadID << "." << std::endl; 383 } 384 } 385 386 std::string TclThreadManager::popCommandFront(unsigned int threadID) 387 { 388 // mutex threadqueues 389 boost::mutex::scoped_lock lock(this->threadQueuesMutex_); 390 391 std::map<unsigned int, std::pair<std::queue<std::string>, boost::condition*> >::iterator it = this->threadQueues_.find(threadID); 392 if (it != this->threadQueues_.end()) 393 { 394 std::string command = (*it).second.first.front(); 395 (*it).second.first.pop(); 396 return command; 397 } 398 else 399 { 400 COUT(1) << "Error: (" << __LINE__ << ") No Tcl-thread with ID " << threadID << "." << std::endl; 401 return ""; 402 } 403 } 404 405 bool TclThreadManager::isEmpty(unsigned int threadID) 406 { 407 // mutex threadqueues 408 boost::mutex::scoped_lock lock(this->threadQueuesMutex_); 409 410 std::map<unsigned int, std::pair<std::queue<std::string>, boost::condition*> >::const_iterator it = this->threadQueues_.find(threadID); 411 if (it != this->threadQueues_.end()) 412 { 413 return (*it).second.first.empty(); 414 } 415 else 416 { 417 COUT(1) << "Error: (" << __LINE__ << ") No Tcl-thread with ID " << threadID << "." << std::endl; 418 return true; 419 } 420 } 421 422 std::string TclThreadManager::eval(const std::string& command) 423 { 424 // mutex orxstate 425 boost::mutex::scoped_lock lock(this->orxonoxStateMutex_); 426 427 while (!this->isReady_) 428 this->orxonoxEvalCondition_.wait(lock); 429 430 CommandExecutor::execute(command, false); 431 432 if (CommandExecutor::getLastEvaluation().hasReturnvalue()) 433 return CommandExecutor::getLastEvaluation().getReturnvalue().toString(); 434 435 return ""; 436 } 437 438 std::string TclThreadManager::eval(unsigned int threadID, const std::string& command) 439 { 440 { 441 // mutex query 442 boost::mutex::scoped_lock lock(this->orxonoxQueryMutex_); 443 this->isQuerying_ = true; 444 this->queryID_ = threadID; 445 std::cout << "2_0\n"; 446 } 447 448 { 449 // mutex threads 450 boost::mutex::scoped_lock lock(this->threadsMutex_); 451 452 std::map<unsigned int, TclThread*>::iterator it = this->threads_.find(threadID); 453 if (it != this->threads_.end()) 454 { 455 std::cout << "2_1\n"; 456 if (this->getState((*it).second) == TclThread::Ready) 457 { 458 std::cout << "2_2\n"; 459 // mutex threadeval 460 boost::mutex::scoped_lock lock(*(*it).second->evalMutex_); 365 boost::mutex::scoped_lock lock(target->interpreterMutex_, boost::defer_lock_t()); 366 bool successfullyLocked = false; 461 367 try 462 368 { 463 std::cout << "2_3\n"; 464 return (*it).second->interpreter_->eval(command); 369 if (querierID == 0 || std::find(querier->queriers_.begin(), querier->queriers_.end(), (unsigned int)0) != querier->queriers_.end()) 370 successfullyLocked = lock.try_lock(); 371 else 372 { 373 while (!lock.try_lock()) 374 boost::this_thread::yield(); 375 376 successfullyLocked = true; 377 } 378 } catch (...) {} 379 380 if (successfullyLocked) 381 { 382 try 383 { output = (std::string)target->interpreter_->eval(command); } 384 catch (Tcl::tcl_error const &e) 385 { this->forceCommandToFrontOfQueue("error Tcl error: " + (std::string)e.what()); } 386 catch (std::exception const &e) 387 { this->forceCommandToFrontOfQueue("error Error while executing Tcl: " + (std::string)e.what()); } 465 388 } 466 catch (Tcl::tcl_error const &e)389 else 467 390 { 468 COUT(1) << "Tcl error: " << e.what() << std::endl; 469 } 470 catch (std::exception const &e) 471 { 472 COUT(1) << "Error while executing Tcl: " << e.what() << std::endl; 473 } 474 std::cout << "2_4\n"; 475 } 476 else 477 { 478 COUT(1) << "Error: Tcl-thread with ID " << threadID << " is not ready. Wait until it's finished or start a new thread." << std::endl; 479 } 480 } 481 else 482 { 483 COUT(1) << "Error: (" << __LINE__ << ") No Tcl-thread with ID " << threadID << "." << std::endl; 484 } 485 } 486 487 { 488 // mutex query 489 boost::mutex::scoped_lock lock(this->orxonoxQueryMutex_); 490 this->isQuerying_ = false; 491 this->queryID_ = 0; 492 std::cout << "2_5\n"; 493 } 494 495 return ""; 496 } 497 498 void TclThreadManager::tick(float dt) 499 { 500 { 501 // mutex orxstate 502 boost::mutex::scoped_lock lock(this->orxonoxStateMutex_); 503 this->isReady_ = true; 504 } 505 506 this->orxonoxEvalCondition_.notify_one(); 507 boost::this_thread::yield(); 508 509 { 510 // mutex orxstate 511 boost::mutex::scoped_lock lock(this->orxonoxStateMutex_); 512 this->isReady_ = false; 513 } 514 515 unsigned long maxtime = (unsigned long)(dt * 1000000 * TCLTHREAD_MAX_CPU_USAGE); 516 Ogre::Timer timer; 517 while (!TclThreadManager::getInstance().isEmpty()) 518 { 519 CommandExecutor::execute(TclThreadManager::getInstance().popCommandFront(), false); 520 if (timer.getMicroseconds() > maxtime) 521 break; 522 } 523 } 524 525 void tclThreadLoop(TclThread* tclThread) 526 { 527 while (true) 528 { 529 if (!TclThreadManager::getInstance().isEmpty(tclThread->threadID_)) 530 { 531 std::cout << "a\n"; 532 TclThreadManager::getInstance().setState(tclThread, TclThread::Busy); 533 // if (!TclThreadManager::getInstance().isEmpty(tclThread->threadID_)) 534 { 535 try 536 { 537 std::cout << "c\n"; 538 throw std::exception(); 539 std::cout << "d\n"; 540 } 541 catch (...) 542 { 543 std::cout << "e\n"; 391 this->forceCommandToFrontOfQueue("error Error: Couldn't query Tcl-interpreter with ID " + getConvertedValue<unsigned int, std::string>(threadID) + ", interpreter is busy right now."); 544 392 } 545 393 } 546 TclThreadManager::getInstance().setState(tclThread, TclThread::Ready); 547 std::cout << "f\n"; 548 549 // boost::this_thread::yield(); 550 // if (TclThreadManager::getInstance().getState(tclThread) == TclThread::Finished) 551 // return; 552 } 553 } 554 555 /* while (true) 556 { 557 TclThreadManager::getInstance().setState(tclThread, TclThread::Busy); 558 while (!TclThreadManager::getInstance().isEmpty(tclThread->threadID_)) 559 { 560 try 394 395 boost::mutex::scoped_lock lock(target->queriersMutex_); 396 target->queriers_.clear(); 397 } 398 } 399 return output; 400 } 401 402 void TclThreadManager::tick(float dt) 403 { 404 { 405 this->orxonoxEvalCondition_.notify_one(); 406 boost::this_thread::yield(); 407 } 408 409 { 410 boost::mutex::scoped_lock lock(this->bundlesMutex_); 411 for (std::map<unsigned int, TclInterpreterBundle*>::iterator it = this->interpreterBundles_.begin(); it != this->interpreterBundles_.end(); ++it) 412 { 413 boost::mutex::scoped_lock lock((*it).second->queueMutex_); 414 if (!(*it).second->queue_.empty()) 561 415 { 562 std::cout << "1_1\n"; 563 // mutex threadeval 564 boost::mutex::scoped_lock lock(*tclThread->evalMutex_); 565 tclThread->interpreter_->eval(TclThreadManager::getInstance().popCommandFront(tclThread->threadID_)); 566 std::cout << "1_2\n"; 416 std::string command = (*it).second->queue_.front(); 417 (*it).second->queue_.pop_front(); 418 419 { 420 boost::mutex::scoped_lock lock((*it).second->finishedMutex_); 421 (*it).second->finished_ = false; 422 } 423 424 boost::thread(boost::bind(&tclThread, (*it).second, command)); 567 425 } 568 catch (Tcl::tcl_error const &e) 569 { 570 TclThreadManager::getInstance().pushCommandBack("error Tcl error (thread " + getConvertedValue<unsigned int, std::string>(tclThread->threadID_) + "): " + e.what()); 571 } 572 catch (std::exception const &e) 573 { 574 TclThreadManager::getInstance().pushCommandBack("error Error while executing Tcl (thread " + getConvertedValue<unsigned int, std::string>(tclThread->threadID_) + "): " + e.what()); 575 } 576 std::cout << "1_4\n"; 577 } 578 TclThreadManager::getInstance().setState(tclThread, TclThread::Ready); 579 580 while (TclThreadManager::getInstance().isEmpty(tclThread->threadID_)) 581 { 582 boost::this_thread::yield(); 583 if (TclThreadManager::getInstance().getState(tclThread) == TclThread::Finished) 584 return; 585 } 586 }*/ 426 } 427 } 428 429 { 430 boost::mutex::scoped_lock lock(this->orxonoxInterpreterBundle_.interpreterMutex_); 431 unsigned long maxtime = (unsigned long)(dt * 1000000 * TCLTHREADMANAGER_MAX_CPU_USAGE); 432 Ogre::Timer timer; 433 while (!this->queueIsEmpty()) 434 { 435 CommandExecutor::execute(this->popCommandFromQueue(), false); 436 if (timer.getMicroseconds() > maxtime) 437 break; 438 } 439 } 440 } 441 442 void tclThread(TclInterpreterBundle* interpreterBundle, std::string command) 443 { 444 try 445 { 446 boost::mutex::scoped_lock lock(interpreterBundle->interpreterMutex_); 447 interpreterBundle->interpreter_->eval(command); 448 } 449 catch (Tcl::tcl_error const &e) 450 { 451 TclThreadManager::getInstance().forceCommandToFrontOfQueue("error Tcl (ID " + getConvertedValue<unsigned int, std::string>(interpreterBundle->id_) + ") error: " + e.what()); 452 } 453 catch (std::exception const &e) 454 { 455 TclThreadManager::getInstance().forceCommandToFrontOfQueue("error Error while executing Tcl (ID " + getConvertedValue<unsigned int, std::string>(interpreterBundle->id_) + "): " + e.what()); 456 } 457 458 boost::mutex::scoped_lock lock(interpreterBundle->finishedMutex_); 459 interpreterBundle->finished_ = true; 460 interpreterBundle->finishedCondition_.notify_all(); 587 461 } 588 462 } -
code/branches/console/src/core/TclThreadManager.h
r1247 r1255 31 31 32 32 #include <queue> 33 #include <map> 34 #include <list> 33 35 34 36 #include <boost/thread/mutex.hpp> … … 43 45 class boost::thread; 44 46 45 struct TclThread47 struct _CoreExport TclInterpreterBundle 46 48 { 47 unsigned int threadID_; 49 unsigned int id_; 50 51 std::list<std::string> queue_; 52 boost::mutex queueMutex_; 53 48 54 Tcl::interpreter* interpreter_; 49 boost::thread* thread_; 50 boost::mutex* evalMutex_; 51 boost::mutex* stateMutex_; 52 enum State 53 { 54 Ready, 55 Busy, 56 Finished, 57 Error 58 }* state_; 55 std::string interpreterName_; 56 boost::try_mutex interpreterMutex_; 57 58 std::list<unsigned int> queriers_; 59 boost::mutex queriersMutex_; 60 61 bool running_; 62 boost::mutex runningMutex_; 63 64 bool finished_; 65 boost::mutex finishedMutex_; 66 boost::condition finishedCondition_; 59 67 }; 60 68 … … 64 72 static TclThreadManager& getInstance(); 65 73 66 static void tclthread(unsigned int threadID, const std::string& command);67 74 static unsigned int create(); 68 75 static void destroy(unsigned int threadID); 69 76 static void execute(unsigned int threadID, const std::string& command); 70 77 static std::string query(unsigned int threadID, const std::string& command); 71 static void status();72 static void dump(unsigned int threadID);73 78 74 static std::string tcl_query(int id, Tcl::object const &args);75 79 static void tcl_execute(Tcl::object const &args); 80 static std::string tcl_query(int querierID, Tcl::object const &args); 81 static std::string tcl_crossquery(int querierID, int threadID, Tcl::object const &args); 82 static bool tcl_running(int threadID); 76 83 77 Tcl::interpreter* create TclInterpreter(unsigned int threadID) const;78 bool createTclThread();79 bool destroyTclThread(unsigned int threadID);84 Tcl::interpreter* createNewTclInterpreter(const std::string& threadID); 85 TclInterpreterBundle* getInterpreterBundle(unsigned int threadID); 86 std::string dumpList(const std::list<unsigned int>& list); 80 87 81 void setState(TclThread* tclThread, TclThread::State state); 82 TclThread::State getState(TclThread* tclThread); 88 void pushCommandToQueue(const std::string& command); 89 void forceCommandToFrontOfQueue(const std::string& command); 90 std::string popCommandFromQueue(); 91 bool queueIsEmpty(); 83 92 84 void pushCommand Back(const std::string& command);85 std::string popCommandFro nt();86 bool isEmpty();93 void pushCommandToQueue(unsigned int threadID, const std::string& command); 94 std::string popCommandFromQueue(unsigned int threadID); 95 bool queueIsEmpty(unsigned int threadID); 87 96 88 void pushCommandBack(unsigned int threadID, const std::string& command); 89 std::string popCommandFront(unsigned int threadID); 90 bool isEmpty(unsigned int threadID); 97 bool updateQueriersList(TclInterpreterBundle* querier, TclInterpreterBundle* target); 91 98 92 std::string eval (const std::string& command);93 std::string eval (unsigned int threadID, const std::string& command);99 std::string evalQuery(unsigned int querierID, const std::string& command); 100 std::string evalQuery(unsigned int querierID, unsigned int threadID, const std::string& command); 94 101 95 102 virtual void tick(float dt); … … 97 104 private: 98 105 TclThreadManager(); 106 TclThreadManager(const TclThreadManager& other); 107 ~TclThreadManager() {} 99 108 100 bool isReady_; 101 bool isQuerying_; 102 unsigned int queryID_; 103 104 unsigned int IDcount_; 105 std::map<unsigned int, TclThread*> threads_; 106 std::map<unsigned int, std::pair<std::queue<std::string>, boost::condition*> > threadQueues_; 107 std::queue<std::string> orxonoxQueue_; 108 109 boost::try_mutex orxonoxQueueMutex_; 110 boost::try_mutex threadQueuesMutex_; 111 boost::try_mutex threadsMutex_; 112 boost::try_mutex orxonoxStateMutex_; 113 boost::try_mutex orxonoxQueryMutex_; 114 115 boost::condition orxonoxQueueCondition_; 109 unsigned int threadCounter_; 110 TclInterpreterBundle orxonoxInterpreterBundle_; 111 std::map<unsigned int, TclInterpreterBundle*> interpreterBundles_; 112 boost::mutex bundlesMutex_; 113 boost::condition fullQueueCondition_; 116 114 boost::condition orxonoxEvalCondition_; 117 115 }; 118 116 119 _CoreExport void tclThread Loop(TclThread* tclThread);117 _CoreExport void tclThread(TclInterpreterBundle* interpreterBundle, std::string command); 120 118 } 121 119
Note: See TracChangeset
for help on using the changeset viewer.