Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

Changeset 1255


Ignore:
Timestamp:
May 12, 2008, 2:50:21 PM (16 years ago)
Author:
landauf
Message:
  • after a total rewrite of the TclThreadManager, there are some new problems, but most of the old ones are fixed. i commit this version to have a backup, not because it's finished.
  • 'exec' command is now called 'source' (tcl and orxonox)
  • 'orxonox' command is now called 'query' (tcl only)
  • added 'crossquery' command (tcl only)
Location:
code/branches/console/src/core
Files:
7 edited

Legend:

Unmodified
Added
Removed
  • code/branches/console/src/core/CommandExecutor.cc

    r1230 r1255  
    4848    ConsoleCommandShortcutGeneric(keyword3, createExecutor((FunctorStatic*)0, "bind", AccessLevel::User));
    4949
    50     ConsoleCommandShortcutExtern(exec, AccessLevel::None);
     50    ConsoleCommandShortcutExtern(source, AccessLevel::None);
    5151    ConsoleCommandShortcutExtern(echo, AccessLevel::None);
    5252    ConsoleCommandShortcutExtern(puts, AccessLevel::None);
     
    5656    ConsoleCommandShortcutExtern(write, AccessLevel::None);
    5757
    58     void exec(const std::string& filename)
     58    void source(const std::string& filename)
    5959    {
    6060        static std::set<std::string> executingFiles;
     
    6363        if (it != executingFiles.end())
    6464        {
    65             COUT(1) << "Error: Recurring exec command in \"" << filename << "\". Stopped execution." << std::endl;
     65            COUT(1) << "Error: Recurring source command in \"" << filename << "\". Stopped execution." << std::endl;
    6666            return;
    6767        }
     
    7373        if (!file.is_open())
    7474        {
    75             COUT(1) << "Error: Couldn't execute file \"" << filename << "\"." << std::endl;
     75            COUT(1) << "Error: Couldn't open file \"" << filename << "\"." << std::endl;
    7676            return;
    7777        }
  • code/branches/console/src/core/CommandExecutor.h

    r1230 r1255  
    6363    };
    6464
    65     void exec(const std::string& filename);
     65    void source(const std::string& filename);
    6666    std::string echo(const std::string& text);
    6767    void puts(bool newline, const std::string& test);
  • code/branches/console/src/core/Script.cc

    r1115 r1255  
    6767  {
    6868    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;
    7071  }
    7172
     
    99100
    100101    if (luaTags) luaSource_ = replaceLuaTags(levelString);
    101     COUT(4) << "ParsedSourceCode: " << luaSource_ << std::endl;
     102    COUT(5) << "ParsedSourceCode: " << luaSource_ << std::endl;
    102103  }
    103104
  • code/branches/console/src/core/TclBind.cc

    r1247 r1255  
    3333#include "CommandExecutor.h"
    3434#include "Debug.h"
     35#include "TclThreadManager.h"
    3536#include "TclBind.h"
    3637
     
    7071        {
    7172            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());
    7375            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;   }
    7689        }
    7790    }
     
    88101    }
    89102
    90     void TclBind::tcl_puts(Tcl::object const &args)
     103    std::string TclBind::tcl_query(Tcl::object const &args)
    91104    {
    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;
     105std::cout << "Tcl_query: args: " << args.get() << std::endl;
    98106        std::string command = args.get();
    99107
    100         if (command.size() >= 2 && command[0] == '{' && command[command.size() - 1] == '}')
     108        while (command.size() >= 2 && command[0] == '{' && command[command.size() - 1] == '}')
    101109            command = command.substr(1, command.size() - 2);
    102110
     
    115123        std::string command = args.get();
    116124
    117         if (command.size() >= 2 && command[0] == '{' && command[command.size() - 1] == '}')
     125        while (command.size() >= 2 && command[0] == '{' && command[command.size() - 1] == '}')
    118126            command = command.substr(1, command.size() - 2);
    119127
     
    132140        }
    133141        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;   }
    137143        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;   }
    141145
    142146        return "";
     
    151155        }
    152156        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;   }
    156158        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;   }
    160160
    161161        return false;
  • code/branches/console/src/core/TclBind.h

    r1230 r1255  
    4747            void createTclInterpreter();
    4848            void createNewTclInterpreter();
     49            Tcl::interpreter* getTclInterpreter() const { return this->interpreter_; }
    4950
    50             static void tcl_puts(Tcl::object const &args);
    51 
     51            static std::string tcl_query(Tcl::object const &args);
    5252            static void tcl_execute(Tcl::object const &args);
    53             static std::string tcl_orxonox(Tcl::object const &args);
    5453
    5554            static bool eval(const std::string& tclcode);
  • code/branches/console/src/core/TclThreadManager.cc

    r1247 r1255  
    4343#include "util/Convert.h"
    4444
    45 #define TCLTHREAD_MAX_QUEUE_LENGTH 1024
    46 #define TCLTHREAD_MAX_CPU_USAGE 0.50
     45#define TCLTHREADMANAGER_MAX_QUEUE_LENGTH 1024
     46#define TCLTHREADMANAGER_MAX_CPU_USAGE 0.50
    4747
    4848namespace orxonox
    4949{
    50     ConsoleCommand(TclThreadManager, tclthread, AccessLevel::None, true);
     50//    ConsoleCommand(TclThreadManager, tclthread, AccessLevel::None, true);
    5151    ConsoleCommand(TclThreadManager, create,    AccessLevel::None, false);
    5252    ConsoleCommand(TclThreadManager, destroy,   AccessLevel::None, false);
    5353    ConsoleCommand(TclThreadManager, execute,   AccessLevel::None, false);
    5454    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);
    5757
    5858    TclThreadManager* instance = &TclThreadManager::getInstance();
     
    6262        RegisterRootObject(TclThreadManager);
    6363
    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();
    6867    }
    6968
     
    7473    }
    7574
    76     void TclThreadManager::tclthread(unsigned int threadID, const std::string& command)
    77     {
    78         TclThreadManager::execute(threadID, command);
    79     }
    80 
    8175    unsigned int TclThreadManager::create()
    8276    {
    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_;
    8990    }
    9091
    9192    void TclThreadManager::destroy(unsigned int threadID)
    9293    {
    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            }
    96115        }
    97116    }
     
    99118    void TclThreadManager::execute(unsigned int threadID, const std::string& command)
    100119    {
    101         TclThreadManager::getInstance().pushCommandBack(threadID, command);
     120        TclThreadManager::getInstance().pushCommandToQueue(threadID, command);
    102121    }
    103122
    104123    std::string TclThreadManager::query(unsigned int threadID, const std::string& command)
    105124    {
    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);
    193126    }
    194127
    195128    void TclThreadManager::tcl_execute(Tcl::object const &args)
    196129    {
    197 std::cout << "Tcl-thread_execute: args: " << args.get() << std::endl;
    198130        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 query
    211             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 
    221131        while (command.size() >= 2 && command[0] == '{' && command[command.size() - 1] == '}')
    222132            command = command.substr(1, command.size() - 2);
    223133
    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)
    228167    {
    229168        Tcl::interpreter* i = 0;
    230169        i = new Tcl::interpreter(TclBind::getInstance().getTclLibPath());
    231170
    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);
    236171        try
    237172        {
    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
    241186            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\" }");
    242192        }
    243193        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;   }
    247195        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;   }
    251197
    252198        return i;
    253199    }
    254200
    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();
    274298        }
    275299        return true;
    276300    }
    277301
    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))
    302364                {
    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;
    461367                    try
    462368                    {
    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());   }
    465388                    }
    466                     catch (Tcl::tcl_error const &e)
     389                    else
    467390                    {
    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.");
    544392                    }
    545393                }
    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())
    561415                {
    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));
    567425                }
    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();
    587461    }
    588462}
  • code/branches/console/src/core/TclThreadManager.h

    r1247 r1255  
    3131
    3232#include <queue>
     33#include <map>
     34#include <list>
    3335
    3436#include <boost/thread/mutex.hpp>
     
    4345    class boost::thread;
    4446
    45     struct TclThread
     47    struct _CoreExport TclInterpreterBundle
    4648    {
    47         unsigned int threadID_;
     49        unsigned int id_;
     50
     51        std::list<std::string> queue_;
     52        boost::mutex queueMutex_;
     53
    4854        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_;
    5967    };
    6068
     
    6472            static TclThreadManager& getInstance();
    6573
    66             static void tclthread(unsigned int threadID, const std::string& command);
    6774            static unsigned int create();
    6875            static void destroy(unsigned int threadID);
    6976            static void execute(unsigned int threadID, const std::string& command);
    7077            static std::string query(unsigned int threadID, const std::string& command);
    71             static void status();
    72             static void dump(unsigned int threadID);
    7378
    74             static std::string tcl_query(int id, Tcl::object const &args);
    7579            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);
    7683
    77             Tcl::interpreter* createTclInterpreter(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);
    8087
    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();
    8392
    84             void pushCommandBack(const std::string& command);
    85             std::string popCommandFront();
    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);
    8796
    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);
    9198
    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);
    94101
    95102            virtual void tick(float dt);
     
    97104        private:
    98105            TclThreadManager();
     106            TclThreadManager(const TclThreadManager& other);
     107            ~TclThreadManager() {}
    99108
    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_;
    116114            boost::condition orxonoxEvalCondition_;
    117115    };
    118116
    119     _CoreExport void tclThreadLoop(TclThread* tclThread);
     117    _CoreExport void tclThread(TclInterpreterBundle* interpreterBundle, std::string command);
    120118}
    121119
Note: See TracChangeset for help on using the changeset viewer.