Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/branches/console/src/core/TclThreadManager.cc @ 1317

Last change on this file since 1317 was 1276, checked in by landauf, 17 years ago

someone likes to chat? well, I do. here's a new IRC client. it connects directly into our irc.datacore.ch / #orxonox channel with a random nickname. use the "say text" command to write text into the channel. there are some more commands without a shortcut, type "IRC" and tab.
please update your media directory.

for some reason, irc-client and telnet-remote don't work together. please use only one feature at the same time. I'm not sure if it's a bug in TCL or in my TclThreadManager class. The problem also occurs with irc or telnet in parallel with another busy tcl-thread… strange thing.

File size: 24.1 KB
RevLine 
[1230]1/*
2 *   ORXONOX - the hottest 3D action shooter ever to exist
3 *                    > www.orxonox.net <
4 *
5 *
6 *   License notice:
7 *
8 *   This program is free software; you can redistribute it and/or
9 *   modify it under the terms of the GNU General Public License
10 *   as published by the Free Software Foundation; either version 2
11 *   of the License, or (at your option) any later version.
12 *
13 *   This program is distributed in the hope that it will be useful,
14 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
15 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16 *   GNU General Public License for more details.
17 *
18 *   You should have received a copy of the GNU General Public License
19 *   along with this program; if not, write to the Free Software
20 *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
21 *
22 *   Author:
23 *      Fabian 'x3n' Landau
24 *   Co-authors:
25 *      ...
26 *
27 */
28
29#include <iostream>
30#include <string>
31
32#include <boost/thread/thread.hpp>
33#include <boost/bind.hpp>
34
35#include <OgreTimer.h>
36
37#include "CoreIncludes.h"
38#include "ConsoleCommand.h"
39#include "CommandExecutor.h"
40#include "Debug.h"
41#include "TclBind.h"
42#include "TclThreadManager.h"
43#include "util/Convert.h"
44
[1257]45#define TCLTHREADMANAGER_MAX_QUEUE_LENGTH 100
[1255]46#define TCLTHREADMANAGER_MAX_CPU_USAGE 0.50
[1230]47
48namespace orxonox
49{
[1269]50    ConsoleCommandShortcutGeneric(tclexecute, createExecutor(createFunctor(&TclThreadManager::execute), "tclexecute", AccessLevel::None));
51    ConsoleCommandShortcutGeneric(tclquery,   createExecutor(createFunctor(&TclThreadManager::query),   "tclquery",   AccessLevel::None));
[1230]52    ConsoleCommand(TclThreadManager, create,    AccessLevel::None, false);
53    ConsoleCommand(TclThreadManager, destroy,   AccessLevel::None, false);
54    ConsoleCommand(TclThreadManager, execute,   AccessLevel::None, false);
55    ConsoleCommand(TclThreadManager, query,     AccessLevel::None, false);
[1269]56    ConsoleCommand(TclThreadManager, status,    AccessLevel::None, false);
57    ConsoleCommand(TclThreadManager, dump,      AccessLevel::None, false);
58    ConsoleCommand(TclThreadManager, flush,     AccessLevel::None, false);
[1230]59
[1276]60    TclThreadManager* instance_tclthreadmanager = &TclThreadManager::getInstance();
[1230]61
62    TclThreadManager::TclThreadManager()
63    {
64        RegisterRootObject(TclThreadManager);
65
[1255]66        this->threadCounter_ = 0;
67        this->orxonoxInterpreterBundle_.id_ = 0;
68        this->orxonoxInterpreterBundle_.interpreter_ = TclBind::getInstance().getTclInterpreter();
[1257]69        this->threadID_ = boost::this_thread::get_id();
[1230]70    }
71
72    TclThreadManager& TclThreadManager::getInstance()
73    {
74        static TclThreadManager instance;
75        return instance;
76    }
77
[1255]78    unsigned int TclThreadManager::create()
[1230]79    {
[1257]80        boost::mutex::scoped_lock bundles_lock(TclThreadManager::getInstance().bundlesMutex_);
[1255]81        TclThreadManager::getInstance().threadCounter_++;
82        std::string name = getConvertedValue<unsigned int, std::string>(TclThreadManager::getInstance().threadCounter_);
[1230]83
[1255]84        TclInterpreterBundle* bundle = new TclInterpreterBundle;
85        bundle->id_ = TclThreadManager::getInstance().threadCounter_;
86        bundle->interpreter_ = TclThreadManager::getInstance().createNewTclInterpreter(name);
87        bundle->interpreterName_ = name;
88        bundle->running_ = true;
[1257]89        bundle->finished_ = true;
[1255]90
91        TclThreadManager::getInstance().interpreterBundles_[TclThreadManager::getInstance().threadCounter_] = bundle;
92        COUT(0) << "Created new Tcl-interpreter with ID " << TclThreadManager::getInstance().threadCounter_ << std::endl;
93        return TclThreadManager::getInstance().threadCounter_;
[1230]94    }
95
[1276]96    unsigned int TclThreadManager::createID(unsigned int threadID)
97    {
98        unsigned int temp = TclThreadManager::getInstance().threadCounter_;
99        TclThreadManager::getInstance().threadCounter_ = threadID - 1;
100        TclThreadManager::create();
101        TclThreadManager::getInstance().threadCounter_ = temp;
102        return threadID;
103    }
104
[1230]105    void TclThreadManager::destroy(unsigned int threadID)
106    {
[1255]107        TclInterpreterBundle* bundle = TclThreadManager::getInstance().getInterpreterBundle(threadID);
108        if (bundle)
[1230]109        {
[1255]110            {
[1257]111                boost::mutex::scoped_lock running_lock(bundle->runningMutex_);
[1255]112                bundle->running_ = false;
113            }
[1257]114            while (true)
[1255]115            {
[1257]116                {
117                    boost::mutex::scoped_lock finished_lock(bundle->finishedMutex_);
118                    if (bundle->finished_)
119                    {
120                        boost::mutex::scoped_lock bundles_lock(TclThreadManager::getInstance().bundlesMutex_);
121                        boost::mutex::scoped_lock interpreter_lock(bundle->interpreterMutex_, boost::defer_lock_t());
122                        try
123                        {
124                            while (!interpreter_lock.try_lock())
125                            {
126                                TclThreadManager::getInstance().orxonoxEvalCondition_.notify_one();
127                                boost::this_thread::yield();
128                            }
129                        } catch (...) {}
130                        delete bundle->interpreter_;
131                        delete bundle;
132                        TclThreadManager::getInstance().interpreterBundles_.erase(threadID);
133                        break;
134                    }
135                }
136
137                TclThreadManager::getInstance().orxonoxEvalCondition_.notify_one();
138                boost::this_thread::yield();
[1255]139            }
[1257]140
141            COUT(0) << "Destroyed Tcl-interpreter with ID " << threadID << std::endl;
[1230]142        }
143    }
144
[1269]145    void TclThreadManager::execute(unsigned int threadID, const std::string& _command)
[1230]146    {
[1276]147        std::string command = stripEnclosingBraces(_command);
[1269]148
149        if (threadID == 0)
150            TclThreadManager::getInstance().pushCommandToQueue(command);
151        else
152            TclThreadManager::getInstance().pushCommandToQueue(threadID, command);
[1230]153    }
154
155    std::string TclThreadManager::query(unsigned int threadID, const std::string& command)
156    {
[1255]157        return TclThreadManager::getInstance().evalQuery(TclThreadManager::getInstance().orxonoxInterpreterBundle_.id_, threadID, command);
[1230]158    }
159
[1269]160    void TclThreadManager::status()
161    {
162        COUT(0) << "Thread ID" << '\t' << "Queue size" << '\t' << "State" << std::endl;
163
164        std::string output = "Orxonox";
165        output += "\t\t";
166        {
167            boost::mutex::scoped_lock queue_lock(TclThreadManager::getInstance().orxonoxInterpreterBundle_.queueMutex_);
168            output += getConvertedValue<unsigned int, std::string>(TclThreadManager::getInstance().orxonoxInterpreterBundle_.queue_.size());
169        }
170        output += "\t\t";
171        output += "busy";
172        COUT(0) << output << std::endl;
173
174        boost::mutex::scoped_lock bundles_lock(TclThreadManager::getInstance().bundlesMutex_);
175        for (std::map<unsigned int, TclInterpreterBundle*>::const_iterator it = TclThreadManager::getInstance().interpreterBundles_.begin(); it != TclThreadManager::getInstance().interpreterBundles_.end(); ++it)
176        {
177            std::string output = getConvertedValue<unsigned int, std::string>((*it).first);
178            output += "\t\t";
179            {
180                boost::mutex::scoped_lock queue_lock((*it).second->queueMutex_);
181                output += getConvertedValue<unsigned int, std::string>((*it).second->queue_.size());
182            }
183            output += "\t\t";
184            {
185                boost::mutex::scoped_lock interpreter_lock((*it).second->interpreterMutex_, boost::defer_lock_t());
186                if (interpreter_lock.try_lock())
187                    output += "ready";
188                else
189                    output += "busy";
190            }
191            COUT(0) << output << std::endl;
192        }
193    }
194
195    void TclThreadManager::dump(unsigned int threadID)
196    {
197        TclInterpreterBundle* bundle = 0;
198        if (threadID == 0)
199        {
200            bundle = &TclThreadManager::getInstance().orxonoxInterpreterBundle_;
201            COUT(0) << "Queue dump of Orxonox:" << std::endl;
202        }
203        else
204        {
205            if (bundle = TclThreadManager::getInstance().getInterpreterBundle(threadID))
206            {
207                COUT(0) << "Queue dump of Tcl-thread " << threadID << ":" << std::endl;
208            }
209            else
210                return;
211        }
212
213        boost::mutex::scoped_lock queue_lock(bundle->queueMutex_);
214        unsigned int index = 0;
215        for (std::list<std::string>::const_iterator it = bundle->queue_.begin(); it != bundle->queue_.end(); ++it)
216        {
217            index++;
218            COUT(0) << index << ": " << (*it) << std::endl;
219        }
220    }
221
222    void TclThreadManager::flush(unsigned int threadID)
223    {
224        TclInterpreterBundle* bundle = 0;
225        if (threadID == 0)
226            bundle = &TclThreadManager::getInstance().orxonoxInterpreterBundle_;
227        else
228            if (!(bundle = TclThreadManager::getInstance().getInterpreterBundle(threadID)))
229                return;
230
231        boost::mutex::scoped_lock queue_lock(bundle->queueMutex_);
232        bundle->queue_.clear();
233        if (threadID == 0)
234        {
235            COUT(0) << "Flushed queue of Orxonox Tcl-interpreter." << std::endl;
236        }
237        else
238        {
239            COUT(0) << "Flushed queue of Tcl-interpreter " << threadID << "." << std::endl;
240        }
241    }
242
[1255]243    void TclThreadManager::tcl_execute(Tcl::object const &args)
[1247]244    {
[1276]245        TclThreadManager::getInstance().pushCommandToQueue(stripEnclosingBraces(args.get()));
[1247]246    }
247
[1255]248    std::string TclThreadManager::tcl_query(int querierID, Tcl::object const &args)
[1247]249    {
[1276]250        return TclThreadManager::getInstance().evalQuery((unsigned int)querierID, stripEnclosingBraces(args.get()));
[1247]251    }
252
[1255]253    std::string TclThreadManager::tcl_crossquery(int querierID, int threadID, Tcl::object const &args)
[1230]254    {
[1276]255        return TclThreadManager::getInstance().evalQuery((unsigned int)querierID, (unsigned int)threadID, stripEnclosingBraces(args.get()));
[1230]256    }
257
[1255]258    bool TclThreadManager::tcl_running(int threadID)
[1230]259    {
[1255]260        TclInterpreterBundle* bundle = TclThreadManager::getInstance().getInterpreterBundle((unsigned int)threadID);
261        if (bundle)
[1247]262        {
[1257]263            boost::mutex::scoped_lock running_lock(bundle->runningMutex_);
[1255]264            return bundle->running_;
[1247]265        }
[1255]266        return false;
[1230]267    }
268
[1255]269    Tcl::interpreter* TclThreadManager::createNewTclInterpreter(const std::string& threadID)
[1230]270    {
[1247]271        Tcl::interpreter* i = 0;
272        i = new Tcl::interpreter(TclBind::getInstance().getTclLibPath());
[1230]273
[1247]274        try
275        {
[1255]276            i->def("orxonox::query", TclThreadManager::tcl_query, Tcl::variadic());
277            i->def("orxonox::crossquery", TclThreadManager::tcl_crossquery, Tcl::variadic());
278            i->def("orxonox::execute", TclThreadManager::tcl_execute, Tcl::variadic());
279            i->def("orxonox::running", TclThreadManager::tcl_running);
280
281            i->def("execute", TclThreadManager::tcl_execute, Tcl::variadic());
282            i->eval("proc query args { orxonox::query " + threadID + " $args }");
283            i->eval("proc crossquery {id args} { orxonox::crossquery " + threadID + " $id $args }");
284            i->eval("set id " + threadID);
285
286            i->eval("rename exit tcl::exit");
287            i->eval("proc exit {} { orxonox TclThreadManager destroy " + threadID + " }");
288
[1247]289            i->eval("redef_puts");
[1255]290
[1267]291//            i->eval("rename while tcl::while");
292//            i->eval("proc while {test command} { tcl::while {[uplevel 1 expr $test]} {uplevel 1 $command} }"); // (\"$test\" && [orxonox::running " + threadID + "]])
[1255]293//            i->eval("rename for tcl::for");
294//            i->eval("proc for {start test next command} { uplevel tcl::for \"$start\" \"$test\" \"$next\" \"$command\" }");
[1247]295        }
296        catch (Tcl::tcl_error const &e)
[1255]297        {   COUT(1) << "Tcl error while creating Tcl-interpreter (" << threadID << "): " << e.what() << std::endl;   }
[1247]298        catch (std::exception const &e)
[1255]299        {   COUT(1) << "Error while creating Tcl-interpreter (" << threadID << "): " << e.what() << std::endl;   }
[1230]300
301        return i;
302    }
303
[1255]304    TclInterpreterBundle* TclThreadManager::getInterpreterBundle(unsigned int threadID)
[1230]305    {
[1257]306        boost::mutex::scoped_lock bundles_lock(this->bundlesMutex_);
[1255]307        std::map<unsigned int, TclInterpreterBundle*>::iterator it = this->interpreterBundles_.find(threadID);
308        if (it != this->interpreterBundles_.end())
[1230]309        {
[1255]310            return (*it).second;
[1230]311        }
[1255]312        else
[1230]313        {
[1257]314            this->error("Error: No Tcl-interpreter with ID " + getConvertedValue<unsigned int, std::string>(threadID) + " existing.");
[1255]315            return 0;
[1230]316        }
317    }
318
[1255]319    std::string TclThreadManager::dumpList(const std::list<unsigned int>& list)
[1230]320    {
[1255]321        std::string output = "";
322        for (std::list<unsigned int>::const_iterator it = list.begin(); it != list.end(); ++it)
[1230]323        {
[1255]324            if (it != list.begin())
325                output += " ";
[1230]326
[1255]327            output += getConvertedValue<unsigned int, std::string>(*it);
[1230]328        }
[1255]329        return output;
[1230]330    }
331
[1257]332    void TclThreadManager::error(const std::string& error)
333    {
334        if (boost::this_thread::get_id() != this->threadID_)
335        {
336            boost::mutex::scoped_lock queue_lock(this->orxonoxInterpreterBundle_.queueMutex_);
337            if (this->orxonoxInterpreterBundle_.queue_.size() >= TCLTHREADMANAGER_MAX_QUEUE_LENGTH)
[1258]338            {
339                boost::this_thread::yield();
[1257]340                return;
[1258]341            }
[1257]342        }
343
344        this->forceCommandToFrontOfQueue("error " + error);
345    }
346
[1276]347    void TclThreadManager::debug(const std::string& error)
348    {
349        if (boost::this_thread::get_id() != this->threadID_)
350        {
351            boost::mutex::scoped_lock queue_lock(this->orxonoxInterpreterBundle_.queueMutex_);
352            if (this->orxonoxInterpreterBundle_.queue_.size() >= TCLTHREADMANAGER_MAX_QUEUE_LENGTH)
353            {
354                boost::this_thread::yield();
355                return;
356            }
357        }
358
359        this->forceCommandToFrontOfQueue("debug " + error);
360    }
361
[1255]362    void TclThreadManager::pushCommandToQueue(const std::string& command)
[1247]363    {
[1257]364        boost::mutex::scoped_lock queue_lock(this->orxonoxInterpreterBundle_.queueMutex_);
[1255]365        while (this->orxonoxInterpreterBundle_.queue_.size() >= TCLTHREADMANAGER_MAX_QUEUE_LENGTH)
[1257]366            this->fullQueueCondition_.wait(queue_lock);
[1255]367
368        this->orxonoxInterpreterBundle_.queue_.push_back(command);
[1247]369    }
370
[1255]371    void TclThreadManager::forceCommandToFrontOfQueue(const std::string& command)
[1247]372    {
[1257]373        boost::mutex::scoped_lock queue_lock(this->orxonoxInterpreterBundle_.queueMutex_);
[1255]374        this->orxonoxInterpreterBundle_.queue_.push_front(command);
[1247]375    }
376
[1255]377    std::string TclThreadManager::popCommandFromQueue()
[1230]378    {
[1257]379        boost::mutex::scoped_lock queue_lock(this->orxonoxInterpreterBundle_.queueMutex_);
[1255]380        std::string temp = this->orxonoxInterpreterBundle_.queue_.front();
381        this->orxonoxInterpreterBundle_.queue_.pop_front();
382        this->fullQueueCondition_.notify_one();
383        return temp;
[1230]384    }
385
[1255]386    bool TclThreadManager::queueIsEmpty()
[1230]387    {
[1257]388        boost::mutex::scoped_lock queue_lock(this->orxonoxInterpreterBundle_.queueMutex_);
[1255]389        return this->orxonoxInterpreterBundle_.queue_.empty();
[1230]390    }
391
[1255]392    void TclThreadManager::pushCommandToQueue(unsigned int threadID, const std::string& command)
[1230]393    {
[1255]394        TclInterpreterBundle* bundle = this->getInterpreterBundle(threadID);
395        if (bundle)
396        {
[1257]397            boost::mutex::scoped_lock queue_lock(bundle->queueMutex_);
[1255]398            if (bundle->queue_.size() >= TCLTHREADMANAGER_MAX_QUEUE_LENGTH)
399            {
[1257]400                this->error("Error: Queue of Tcl-interpreter " + getConvertedValue<unsigned int, std::string>(threadID) + " is full, couldn't add command.");
[1255]401                return;
402            }
[1230]403
[1255]404            bundle->queue_.push_back(command);
405        }
[1230]406    }
407
[1255]408    std::string TclThreadManager::popCommandFromQueue(unsigned int threadID)
[1230]409    {
[1255]410        TclInterpreterBundle* bundle = this->getInterpreterBundle(threadID);
411        if (bundle)
[1230]412        {
[1257]413            boost::mutex::scoped_lock queue_lock(bundle->queueMutex_);
[1255]414            std::string temp = bundle->queue_.front();
415            bundle->queue_.pop_front();
416            return temp;
[1230]417        }
[1255]418        return "";
[1230]419    }
420
[1255]421    bool TclThreadManager::queueIsEmpty(unsigned int threadID)
[1230]422    {
[1255]423        TclInterpreterBundle* bundle = this->getInterpreterBundle(threadID);
424        if (bundle)
[1230]425        {
[1257]426            boost::mutex::scoped_lock queue_lock(bundle->queueMutex_);
[1255]427            return bundle->queue_.empty();
[1230]428        }
[1255]429        return true;
[1230]430    }
431
[1255]432    bool TclThreadManager::updateQueriersList(TclInterpreterBundle* querier, TclInterpreterBundle* target)
[1230]433    {
[1255]434        if (querier == target)
435            return false;
[1230]436
[1257]437        boost::mutex::scoped_lock queriers_lock(target->queriersMutex_);
[1255]438
[1230]439        {
[1257]440            boost::mutex::scoped_lock queriers_lock(querier->queriersMutex_);
[1255]441            target->queriers_.insert(target->queriers_.end(), querier->queriers_.begin(), querier->queriers_.end());
[1230]442        }
[1255]443
444        target->queriers_.insert(target->queriers_.end(), querier->id_);
445
446        if (std::find(target->queriers_.begin(), target->queriers_.end(), target->id_) != target->queriers_.end())
[1230]447        {
[1257]448            this->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_) + ".");
[1255]449            return false;
[1230]450        }
[1255]451
452        return true;
[1230]453    }
454
[1255]455    std::string TclThreadManager::evalQuery(unsigned int querierID, const std::string& command)
[1230]456    {
[1255]457        TclInterpreterBundle* querier = this->getInterpreterBundle(querierID);
458        std::string output = "";
459        if (querier)
460        {
461            if (this->updateQueriersList(querier, &this->orxonoxInterpreterBundle_))
462            {
[1257]463                boost::mutex::scoped_lock interpreter_lock(this->orxonoxInterpreterBundle_.interpreterMutex_);
464                this->orxonoxEvalCondition_.wait(interpreter_lock);
[1230]465
[1255]466                if (!CommandExecutor::execute(command, false))
[1257]467                    this->error("Error: Can't execute command \"" + command + "\"!");
[1230]468
[1255]469                if (CommandExecutor::getLastEvaluation().hasReturnvalue())
470                    output = CommandExecutor::getLastEvaluation().getReturnvalue().toString();
471            }
[1230]472
[1257]473            boost::mutex::scoped_lock queriers_lock(this->orxonoxInterpreterBundle_.queriersMutex_);
[1255]474            this->orxonoxInterpreterBundle_.queriers_.clear();
475        }
476        return output;
[1230]477    }
478
[1255]479    std::string TclThreadManager::evalQuery(unsigned int querierID, unsigned int threadID, const std::string& command)
[1230]480    {
[1257]481        TclInterpreterBundle* target = 0;
482        if (threadID)
483            target = this->getInterpreterBundle(threadID);
484        else
485            target = &this->orxonoxInterpreterBundle_;
486
[1255]487        std::string output = "";
488        if (target)
[1247]489        {
[1255]490            TclInterpreterBundle* querier = 0;
491            if (querierID)
492                querier = this->getInterpreterBundle(querierID);
493            else
494                querier = &this->orxonoxInterpreterBundle_;
[1230]495
[1255]496            if (querier)
[1230]497            {
[1255]498                if (this->updateQueriersList(querier, target))
[1230]499                {
[1257]500                    boost::mutex::scoped_lock interpreter_lock(target->interpreterMutex_, boost::defer_lock_t());
[1255]501                    bool successfullyLocked = false;
[1247]502                    try
503                    {
[1255]504                        if (querierID == 0 || std::find(querier->queriers_.begin(), querier->queriers_.end(), (unsigned int)0) != querier->queriers_.end())
[1257]505                            successfullyLocked = interpreter_lock.try_lock();
[1255]506                        else
507                        {
[1257]508                            while (!interpreter_lock.try_lock())
[1255]509                                boost::this_thread::yield();
510
511                            successfullyLocked = true;
512                        }
513                    } catch (...) {}
514
515                    if (successfullyLocked)
[1247]516                    {
[1276]517                        this->debug("TclThread_query: " + command);
[1255]518                        try
519                        {   output = (std::string)target->interpreter_->eval(command);   }
520                        catch (Tcl::tcl_error const &e)
[1257]521                        {   this->error("Tcl error: " + (std::string)e.what());   }
[1255]522                        catch (std::exception const &e)
[1257]523                        {   this->error("Error while executing Tcl: " + (std::string)e.what());   }
[1247]524                    }
[1255]525                    else
[1247]526                    {
[1257]527                        this->error("Error: Couldn't query Tcl-interpreter with ID " + getConvertedValue<unsigned int, std::string>(threadID) + ", interpreter is busy right now.");
[1247]528                    }
[1230]529                }
[1255]530
[1257]531                boost::mutex::scoped_lock queriers_lock(target->queriersMutex_);
[1255]532                target->queriers_.clear();
[1230]533            }
534        }
[1255]535        return output;
[1230]536    }
537
538    void TclThreadManager::tick(float dt)
539    {
540        {
[1255]541            this->orxonoxEvalCondition_.notify_one();
542            boost::this_thread::yield();
[1230]543        }
544
545        {
[1257]546            boost::mutex::scoped_lock bundles_lock(this->bundlesMutex_);
[1255]547            for (std::map<unsigned int, TclInterpreterBundle*>::iterator it = this->interpreterBundles_.begin(); it != this->interpreterBundles_.end(); ++it)
[1230]548            {
[1257]549                boost::mutex::scoped_lock queue_lock((*it).second->queueMutex_);
[1255]550                if (!(*it).second->queue_.empty())
[1230]551                {
[1255]552                    std::string command = (*it).second->queue_.front();
553                    (*it).second->queue_.pop_front();
[1247]554                    {
[1257]555                        boost::mutex::scoped_lock finished_lock((*it).second->finishedMutex_);
[1255]556                        (*it).second->finished_ = false;
[1247]557                    }
[1255]558                    boost::thread(boost::bind(&tclThread, (*it).second, command));
[1230]559                }
[1247]560            }
561        }
562
563        {
[1257]564            boost::mutex::scoped_lock interpreter_lock(this->orxonoxInterpreterBundle_.interpreterMutex_);
[1255]565            unsigned long maxtime = (unsigned long)(dt * 1000000 * TCLTHREADMANAGER_MAX_CPU_USAGE);
566            Ogre::Timer timer;
567            while (!this->queueIsEmpty())
[1247]568            {
[1255]569                CommandExecutor::execute(this->popCommandFromQueue(), false);
570                if (timer.getMicroseconds() > maxtime)
571                    break;
[1230]572            }
[1255]573        }
574    }
[1230]575
[1255]576    void tclThread(TclInterpreterBundle* interpreterBundle, std::string command)
577    {
[1276]578        TclThreadManager::getInstance().debug("TclThread_execute: " + command);
[1257]579        boost::mutex::scoped_lock interpreter_lock(interpreterBundle->interpreterMutex_);
[1255]580        try
581        {
582            interpreterBundle->interpreter_->eval(command);
583        }
584        catch (Tcl::tcl_error const &e)
585        {
[1257]586            TclThreadManager::getInstance().error("Tcl (ID " + getConvertedValue<unsigned int, std::string>(interpreterBundle->id_) + ") error: " + e.what());
[1255]587        }
588        catch (std::exception const &e)
589        {
[1257]590            TclThreadManager::getInstance().error("Error while executing Tcl (ID " + getConvertedValue<unsigned int, std::string>(interpreterBundle->id_) + "): " + e.what());
[1255]591        }
592
[1257]593        boost::mutex::scoped_lock finished_lock(interpreterBundle->finishedMutex_);
[1255]594        interpreterBundle->finished_ = true;
595        interpreterBundle->finishedCondition_.notify_all();
[1230]596    }
597}
Note: See TracBrowser for help on using the repository browser.