- Timestamp:
- Jul 28, 2009, 5:04:38 PM (15 years ago)
- Location:
- code/branches/resource/src
- Files:
-
- 7 edited
Legend:
- Unmodified
- Added
- Removed
-
code/branches/resource/src/core/TclBind.cc
r3354 r3360 104 104 Tcl::interpreter* TclBind::createTclInterpreter() 105 105 { 106 Tcl::interpreter* interpreter; 106 Tcl::interpreter* interpreter = new Tcl::interpreter(); 107 std::string libpath = TclBind::getTclLibraryPath(); 108 109 try 110 { 111 if (libpath != "") 112 interpreter->eval("set tcl_library \"" + libpath + "\""); 113 114 Tcl_Init(interpreter->get()); 115 116 interpreter->eval("source \"" + TclBind::getInstance().tclDataPath_ + "/init.tcl\""); 117 } 118 catch (Tcl::tcl_error const &e) 119 { COUT(1) << "Tcl error while creating Tcl-interpreter: " << e.what() << std::endl; COUT(1) << "Error: Tcl isn't properly initialized. Orxonox might possibly not work like that." << std::endl; } 120 catch (std::exception const &e) 121 { COUT(1) << "Error while creating Tcl-interpreter: " << e.what() << std::endl; COUT(1) << "Error: Tcl isn't properly initialized. Orxonox might possibly not work like that." << std::endl; } 122 catch (...) 123 { COUT(1) << "Error while creating Tcl-interpreter." << std::endl; COUT(1) << "Error: Tcl isn't properly initialized. Orxonox might possibly not work like that." << std::endl; } 124 125 return interpreter; 126 } 127 128 std::string TclBind::getTclLibraryPath() 129 { 107 130 #ifdef DEPENDENCY_PACKAGE_ENABLE 108 131 if (Core::isDevelopmentRun()) 109 interpreter = new Tcl::interpreter(std::string(ORXONOX_DEP_LIB_PATH) + "/tcl");132 return (std::string(ORXONOX_DEP_LIB_PATH) + "/tcl"); 110 133 else 111 interpreter = new Tcl::interpreter(Core::getRootPathString() + "lib/tcl");134 return (Core::getRootPathString() + "lib/tcl"); 112 135 #else 113 interpreter = new Tcl::interpreter();136 return ""; 114 137 #endif 115 try116 {117 interpreter->eval("source \"" + TclBind::getInstance().tclDataPath_ + "/init.tcl\"");118 }119 catch (Tcl::tcl_error const &e)120 { COUT(1) << "Tcl error while creating Tcl-interpreter: " << e.what() << std::endl; }121 catch (std::exception const &e)122 { COUT(1) << "Error while creating Tcl-interpreter: " << e.what() << std::endl; }123 catch (...)124 { COUT(1) << "Error while creating Tcl-interpreter." << std::endl; }125 126 return interpreter;127 138 } 128 139 -
code/branches/resource/src/core/TclBind.h
r3344 r3360 50 50 void setDataPath(const std::string& datapath); 51 51 const std::string& getTclDataPath() const { return this->tclDataPath_; } 52 static std::string getTclLibraryPath(); 53 52 54 void initializeTclInterpreter(); 53 55 static Tcl::interpreter* createTclInterpreter(); -
code/branches/resource/src/core/TclThreadManager.cc
r3353 r3360 54 54 SetConsoleCommand(TclThreadManager, execute, false).argumentCompleter(0, autocompletion::tclthreads()); 55 55 SetConsoleCommand(TclThreadManager, query, false).argumentCompleter(0, autocompletion::tclthreads()); 56 SetConsoleCommand(TclThreadManager, source, false).argumentCompleter(0, autocompletion::tclthreads()); 56 57 57 58 /** … … 242 243 newbundle->interpreter_ = TclBind::createTclInterpreter(); 243 244 244 // Initialize the new interpreter 245 try 246 { 247 std::string id_string = getConvertedValue<unsigned int, std::string>(id); 248 249 // Define the functions which are implemented in C++ 250 newbundle->interpreter_->def("::orxonox::execute", TclThreadManager::tcl_execute, Tcl::variadic()); 251 newbundle->interpreter_->def("::orxonox::crossexecute", TclThreadManager::tcl_crossexecute, Tcl::variadic()); 252 newbundle->interpreter_->def("::orxonox::query", TclThreadManager::tcl_query, Tcl::variadic()); 253 newbundle->interpreter_->def("::orxonox::crossquery", TclThreadManager::tcl_crossquery, Tcl::variadic()); 254 newbundle->interpreter_->def("::orxonox::running", TclThreadManager::tcl_running); 255 256 // Create threadspecific shortcuts for the functions above 257 newbundle->interpreter_->def("execute", TclThreadManager::tcl_execute, Tcl::variadic()); 258 newbundle->interpreter_->def("crossexecute", TclThreadManager::tcl_crossexecute, Tcl::variadic()); 259 newbundle->interpreter_->eval("proc query {args} { ::orxonox::query " + id_string + " $args }"); 260 newbundle->interpreter_->eval("proc crossquery {id args} { ::orxonox::crossquery " + id_string + " $id $args }"); 261 newbundle->interpreter_->eval("proc running {} { return [::orxonox::running " + id_string + "] }"); 262 263 // Define a variable containing the thread id 264 newbundle->interpreter_->eval("set id " + id_string); 265 266 // Use our own exit function to avoid shutting down the whole program instead of just the interpreter 267 newbundle->interpreter_->eval("rename exit ::tcl::exit"); 268 newbundle->interpreter_->eval("proc exit {} { execute TclThreadManager destroy " + id_string + " }"); 269 270 // Redefine some native functions 271 newbundle->interpreter_->eval("rename while ::tcl::while"); 272 newbundle->interpreter_->eval("rename ::orxonox::while while"); 273 newbundle->interpreter_->eval("rename for ::tcl::for"); 274 newbundle->interpreter_->eval("rename ::orxonox::for for"); 275 } 276 catch (const Tcl::tcl_error& e) 277 { newbundle->interpreter_ = 0; COUT(1) << "Tcl error while creating Tcl-interpreter (" << id << "): " << e.what() << std::endl; } 278 catch (const std::exception& e) 279 { newbundle->interpreter_ = 0; COUT(1) << "Error while creating Tcl-interpreter (" << id << "): " << e.what() << std::endl; } 280 catch (...) 281 { newbundle->interpreter_ = 0; COUT(1) << "An error occurred while creating a new Tcl-interpreter (" << id << ")" << std::endl; } 245 TclThreadManager::initialize(newbundle); 282 246 283 247 { … … 288 252 289 253 return newbundle->interpreter_; 254 } 255 256 void TclThreadManager::initialize(TclInterpreterBundle* bundle) 257 { 258 std::string id_string = getConvertedValue<unsigned int, std::string>(bundle->id_); 259 260 // Initialize the new interpreter 261 try 262 { 263 // Define the functions which are implemented in C++ 264 bundle->interpreter_->def("::orxonox::execute", TclThreadManager::tcl_execute, Tcl::variadic()); 265 bundle->interpreter_->def("::orxonox::crossexecute", TclThreadManager::tcl_crossexecute, Tcl::variadic()); 266 bundle->interpreter_->def("::orxonox::query", TclThreadManager::tcl_query, Tcl::variadic()); 267 bundle->interpreter_->def("::orxonox::crossquery", TclThreadManager::tcl_crossquery, Tcl::variadic()); 268 bundle->interpreter_->def("::orxonox::running", TclThreadManager::tcl_running); 269 270 // Create threadspecific shortcuts for the functions above 271 bundle->interpreter_->def("execute", TclThreadManager::tcl_execute, Tcl::variadic()); 272 bundle->interpreter_->def("crossexecute", TclThreadManager::tcl_crossexecute, Tcl::variadic()); 273 bundle->interpreter_->eval("proc query {args} { ::orxonox::query " + id_string + " $args }"); 274 bundle->interpreter_->eval("proc crossquery {id args} { ::orxonox::crossquery " + id_string + " $id $args }"); 275 bundle->interpreter_->eval("proc running {} { return [::orxonox::running " + id_string + "] }"); 276 277 // Define a variable containing the thread id 278 bundle->interpreter_->eval("set id " + id_string); 279 280 // Use our own exit function to avoid shutting down the whole program instead of just the interpreter 281 bundle->interpreter_->eval("rename exit ::tcl::exit"); 282 bundle->interpreter_->eval("proc exit {} { execute TclThreadManager destroy " + id_string + " }"); 283 284 // Redefine some native functions 285 bundle->interpreter_->eval("rename while ::tcl::while"); 286 bundle->interpreter_->eval("rename ::orxonox::while while"); 287 bundle->interpreter_->eval("rename for ::tcl::for"); 288 bundle->interpreter_->eval("rename ::orxonox::for for"); 289 } 290 catch (const Tcl::tcl_error& e) 291 { bundle->interpreter_ = 0; COUT(1) << "Tcl error while creating Tcl-interpreter (" << id_string << "): " << e.what() << std::endl; } 292 catch (const std::exception& e) 293 { bundle->interpreter_ = 0; COUT(1) << "Error while creating Tcl-interpreter (" << id_string << "): " << e.what() << std::endl; } 294 catch (...) 295 { bundle->interpreter_ = 0; COUT(1) << "An error occurred while creating a new Tcl-interpreter (" << id_string << ")" << std::endl; } 290 296 } 291 297 … … 403 409 { 404 410 // This query would lead to a deadlock - return with an error 405 this->error("Error: Circular query (" + this->dumpList(source_bundle->queriers_.getList()) + " " + getConvertedValue<unsigned int, std::string>(source_bundle->id_) \411 TclThreadManager::error("Error: Circular query (" + this->dumpList(source_bundle->queriers_.getList()) + " " + getConvertedValue<unsigned int, std::string>(source_bundle->id_) \ 406 412 + " -> " + getConvertedValue<unsigned int, std::string>(target_bundle->id_) \ 407 413 + "), couldn't query Tcl-interpreter with ID " + getConvertedValue<unsigned int, std::string>(target_bundle->id_) \ … … 439 445 { 440 446 // It's a query to the CommandExecutor 441 this->debug("TclThread_query -> CE: " + command);447 TclThreadManager::debug("TclThread_query -> CE: " + command); 442 448 if (!CommandExecutor::execute(command, false)) 443 this->error("Error: Can't execute command \"" + command + "\"!");449 TclThreadManager::error("Error: Can't execute command \"" + command + "\"!"); 444 450 445 451 if (CommandExecutor::getLastEvaluation().hasReturnvalue()) … … 449 455 { 450 456 // It's a query to a Tcl interpreter 451 this->debug("TclThread_query: " + command);452 453 output = this->eval(target_bundle, command);457 TclThreadManager::debug("TclThread_query: " + command); 458 459 output = TclThreadManager::eval(target_bundle, command, "query"); 454 460 } 455 461 … … 468 474 // This happens if the main thread tries to query a busy interpreter 469 475 // To avoid a lock of the main thread, we simply don't proceed with the query in this case 470 this->error("Error: Couldn't query Tcl-interpreter with ID " + getConvertedValue<unsigned int, std::string>(target_bundle->id_) + ", interpreter is busy right now.");476 TclThreadManager::error("Error: Couldn't query Tcl-interpreter with ID " + getConvertedValue<unsigned int, std::string>(target_bundle->id_) + ", interpreter is busy right now."); 471 477 } 472 478 } … … 475 481 476 482 return output; 483 } 484 485 /** 486 @brief Creates a non-interactive Tcl-interpreter which executes a file. 487 */ 488 void TclThreadManager::source(const std::string& file) 489 { 490 boost::thread(boost::bind(&sourceThread, file)); 477 491 } 478 492 … … 506 520 else 507 521 { 508 this->error("Error: No Tcl-interpreter with ID " + getConvertedValue<unsigned int, std::string>(id) + " existing.");522 TclThreadManager::error("Error: No Tcl-interpreter with ID " + getConvertedValue<unsigned int, std::string>(id) + " existing."); 509 523 return 0; 510 524 } … … 548 562 void TclThreadManager::error(const std::string& error) 549 563 { 550 this->messageQueue_->push_back("error " + error);564 TclThreadManager::getInstance().messageQueue_->push_back("error " + error); 551 565 } 552 566 … … 556 570 void TclThreadManager::debug(const std::string& error) 557 571 { 558 this->messageQueue_->push_back("debug " + error);572 TclThreadManager::getInstance().messageQueue_->push_back("debug " + error); 559 573 } 560 574 … … 565 579 Errors are reported through the @ref error function. 566 580 */ 567 std::string TclThreadManager::eval(TclInterpreterBundle* bundle, const std::string& command )581 std::string TclThreadManager::eval(TclInterpreterBundle* bundle, const std::string& command, const std::string& action) 568 582 { 569 583 Tcl_Interp* interpreter = bundle->interpreter_->get(); … … 574 588 if (cc != TCL_OK) 575 589 { 576 this->error("Tcl error (execute, ID " + getConvertedValue<unsigned int, std::string>(bundle->id_) + "): " + static_cast<std::string>(result));590 TclThreadManager::error("Tcl error (" + action + ", ID " + getConvertedValue<unsigned int, std::string>(bundle->id_) + "): " + static_cast<std::string>(result)); 577 591 return ""; 578 592 } … … 594 608 void tclThread(TclInterpreterBundle* bundle, std::string command) 595 609 { 596 TclThreadManager:: getInstance().debug("TclThread_execute: " + command);597 598 TclThreadManager:: getInstance().eval(bundle, command);610 TclThreadManager::debug("TclThread_execute: " + command); 611 612 TclThreadManager::eval(bundle, command, "execute"); 599 613 600 614 bundle->lock_->unlock(); 601 615 } 616 617 /** 618 @brief The main function of a non-interactive source thread. Executes the file. 619 @param file The name of the file that should be executed by the non-interactive interpreter. 620 */ 621 void sourceThread(std::string file) 622 { 623 TclThreadManager::debug("TclThread_source: " + file); 624 625 // Prepare the command-line arguments 626 int argc = 2; 627 char* argv[argc]; 628 argv[0] = "tclthread"; 629 argv[1] = const_cast<char*>(file.c_str()); 630 631 // Start the Tcl-command Tcl_Main with the Tcl_OrxonoxAppInit hook 632 Tcl_Main(argc, argv, Tcl_OrxonoxAppInit); 633 634 // Tcl::object object(file); 635 // int cc = Tcl_FSEvalFile(bundle->interpreter_->get(), object.get_object()); 636 // Tcl::details::result result(bundle->interpreter_->get()); 637 // if (cc != TCL_OK) 638 // TclThreadManager::error("Tcl error (source, ID " + getConvertedValue<unsigned int, std::string>(bundle->id_) + "): " + static_cast<std::string>(result)); 639 // 640 // // Unlock the mutex 641 // bundle->lock_->unlock(); 642 } 643 644 /** 645 @brief A tcl-init hook to inject the non-interactive Tcl-interpreter into the TclThreadManager. 646 */ 647 int Tcl_OrxonoxAppInit(Tcl_Interp* interp) 648 { 649 // Create a new interpreter bundle 650 unsigned int id = TclThreadManager::create(); 651 TclInterpreterBundle* bundle = TclThreadManager::getInstance().getInterpreterBundle(id); 652 653 // Replace the default interpreter in the bundle with the non-interactive one (passed as an argument to this function) 654 if (bundle->interpreter_) 655 delete bundle->interpreter_; 656 bundle->interpreter_ = new Tcl::interpreter(interp, true); 657 658 // Initialize the non-interactive interpreter (like in @ref TclBind::createTclInterpreter but exception safe) 659 std::string libpath = TclBind::getTclLibraryPath(); 660 if (libpath != "") 661 TclThreadManager::eval(bundle, "set tcl_library \"" + libpath + "\"", "source"); 662 int cc = Tcl_Init(interp); 663 TclThreadManager::eval(bundle, "source \"" + TclBind::getInstance().getTclDataPath() + "/init.tcl\"", "source"); 664 665 // Initialize the non-interactive interpreter also with the thread-specific stuff 666 TclThreadManager::initialize(bundle); 667 668 // Lock the mutex (this will be locked until the thread finishes - no chance to interact with the interpreter) 669 bundle->lock_->lock(); 670 671 // Return to Tcl_Main 672 if (!bundle->interpreter_) 673 return TCL_ERROR; 674 else 675 return cc; 676 } 602 677 } -
code/branches/resource/src/core/TclThreadManager.h
r3359 r3360 39 39 #include "OrxonoxClass.h" 40 40 41 class Tcl_Interp; 42 41 43 namespace orxonox 42 44 { … … 45 47 friend class TclBind; 46 48 friend _CoreExport void tclThread(TclInterpreterBundle* bundle, std::string command); 49 friend _CoreExport void sourceThread(std::string file); 50 friend _CoreExport int Tcl_OrxonoxAppInit(Tcl_Interp* interp); 47 51 48 52 public: … … 57 61 static void execute(unsigned int target_id, const std::string& command); 58 62 static std::string query(unsigned int target_id, const std::string& command); 63 static void source(const std::string& file); 59 64 60 void error(const std::string& error);61 void debug(const std::string& error);65 static void error(const std::string& error); 66 static void debug(const std::string& error); 62 67 63 68 void update(const Clock& time); … … 78 83 std::string dumpList(const std::list<unsigned int>& list); 79 84 80 std::string eval(TclInterpreterBundle* bundle, const std::string& command); 85 static void initialize(TclInterpreterBundle* bundle); 86 static std::string eval(TclInterpreterBundle* bundle, const std::string& command, const std::string& action); 81 87 82 88 static TclThreadManager* singletonPtr_s; ///< Singleton pointer … … 90 96 91 97 _CoreExport void tclThread(TclInterpreterBundle* bundle, std::string command); 98 _CoreExport void sourceThread(std::string file); 99 _CoreExport int Tcl_OrxonoxAppInit(Tcl_Interp* interp); 92 100 } 93 101 -
code/branches/resource/src/cpptcl/changes_orxonox.diff
r2710 r3360 28 28 Tcl_SetResult(interp, const_cast<char*>(e.what()), TCL_VOLATILE); 29 29 return TCL_ERROR; 30 @@ -858,6 +858,18 @@31 owner_ = true;32 }33 34 +interpreter::interpreter(string const &libpath)35 +{36 + interp_ = Tcl_CreateInterp();37 + owner_ = true;38 +39 + try40 + {41 + this->eval("set tcl_library \"" + libpath + "\"");42 + Tcl_Init(this->interp_);43 + } catch (...) {}44 +}45 +46 interpreter::interpreter(Tcl_Interp *interp, bool owner)47 {48 interp_ = interp;49 --- cpptcl.h Wed Jan 28 20:56:11 200950 +++ cpptcl.h Sat Jan 24 12:52:54 200951 @@ -467,6 +467,7 @@52 {53 public:54 interpreter();55 + interpreter(std::string const &libpath);56 interpreter(Tcl_Interp *, bool owner = true);57 ~interpreter();58 -
code/branches/resource/src/cpptcl/cpptcl.cc
r3068 r3360 859 859 } 860 860 861 interpreter::interpreter(string const &libpath)862 {863 interp_ = Tcl_CreateInterp();864 owner_ = true;865 866 try867 {868 this->eval("set tcl_library \"" + libpath + "\"");869 Tcl_Init(this->interp_);870 } catch (...) {}871 }872 873 861 interpreter::interpreter(Tcl_Interp *interp, bool owner) 874 862 { -
code/branches/resource/src/cpptcl/cpptcl.h
r3068 r3360 468 468 public: 469 469 interpreter(); 470 interpreter(std::string const &libpath);471 470 interpreter(Tcl_Interp *, bool owner = true); 472 471 ~interpreter();
Note: See TracChangeset
for help on using the changeset viewer.