Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/branches/netp6/src/core/TclThreadManager.cc @ 3264

Last change on this file since 3264 was 3264, checked in by rgrieder, 15 years ago

Moved boost headers from TclThreadmanager.h to the source file.
Also removed the old boost 1.34 commands since Oli requires 1.35 anyway and there have been about three or four new releases of boost since the writing of the code.

  • Property svn:eol-style set to native
File size: 25.2 KB
Line 
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 "TclThreadManager.h"
30
31#include <boost/bind.hpp>
32#include <boost/thread/condition.hpp>
33#include <boost/thread/mutex.hpp>
34#include <boost/thread/thread.hpp>
35#include <OgreTimer.h>
36#include <cpptcl/cpptcl.h>
37
38#include "util/Convert.h"
39#include "util/Debug.h"
40#include "Clock.h"
41#include "CommandExecutor.h"
42#include "ConsoleCommand.h"
43#include "CoreIncludes.h"
44#include "TclBind.h"
45
46namespace orxonox
47{
48    const unsigned int TCLTHREADMANAGER_MAX_QUEUE_LENGTH = 100;
49    const float TCLTHREADMANAGER_MAX_CPU_USAGE = 0.50f;
50
51    SetConsoleCommandShortcutAlias(TclThreadManager, execute, "tclexecute").argumentCompleter(0, autocompletion::tclthreads());
52    SetConsoleCommandShortcutAlias(TclThreadManager, query,   "tclquery"  ).argumentCompleter(0, autocompletion::tclthreads());
53    SetConsoleCommand(TclThreadManager, create,  false);
54    SetConsoleCommand(TclThreadManager, destroy, false).argumentCompleter(0, autocompletion::tclthreads());
55    SetConsoleCommand(TclThreadManager, execute, false).argumentCompleter(0, autocompletion::tclthreads());
56    SetConsoleCommand(TclThreadManager, query,   false).argumentCompleter(0, autocompletion::tclthreads());
57    SetConsoleCommand(TclThreadManager, status,  false);
58    SetConsoleCommand(TclThreadManager, dump,    false).argumentCompleter(0, autocompletion::tclthreads());
59    SetConsoleCommand(TclThreadManager, flush,   false).argumentCompleter(0, autocompletion::tclthreads());
60
61    struct TclInterpreterBundle
62    {
63        unsigned int id_;
64
65        std::list<std::string> queue_;
66        boost::mutex queueMutex_;
67
68        Tcl::interpreter* interpreter_;
69        std::string interpreterName_;
70        boost::try_mutex interpreterMutex_;
71
72        std::list<unsigned int> queriers_;
73        boost::mutex queriersMutex_;
74
75        bool running_;
76        boost::mutex runningMutex_;
77
78        bool finished_;
79        boost::mutex finishedMutex_;
80        boost::condition finishedCondition_;
81    };
82
83
84    static boost::thread::id threadID_g;
85    static boost::mutex bundlesMutex_g;
86    static boost::condition fullQueueCondition_g;
87    static boost::condition orxonoxEvalCondition_g;
88
89    TclThreadManager* TclThreadManager::singletonRef_s = 0;
90
91    TclThreadManager::TclThreadManager(Tcl::interpreter* interpreter)
92    {
93        RegisterRootObject(TclThreadManager);
94
95        assert(singletonRef_s == 0);
96        singletonRef_s = this;
97
98        this->threadCounter_ = 0;
99        this->orxonoxInterpreterBundle_->id_ = 0;
100        this->orxonoxInterpreterBundle_->interpreter_ = interpreter;
101        threadID_g = boost::this_thread::get_id();
102    }
103
104    TclThreadManager::~TclThreadManager()
105    {
106        unsigned int threadID;
107        {
108            boost::mutex::scoped_lock bundles_lock(bundlesMutex_g);
109            if (this->interpreterBundles_.begin() == this->interpreterBundles_.end())
110                return;
111            else
112                threadID = this->interpreterBundles_.begin()->first;
113        }
114        this->destroy(threadID);
115
116        singletonRef_s = 0;
117    }
118
119    unsigned int TclThreadManager::create()
120    {
121        boost::mutex::scoped_lock bundles_lock(bundlesMutex_g);
122        TclThreadManager::getInstance().threadCounter_++;
123        std::string name = getConvertedValue<unsigned int, std::string>(TclThreadManager::getInstance().threadCounter_);
124
125        TclInterpreterBundle* bundle = new TclInterpreterBundle;
126        bundle->id_ = TclThreadManager::getInstance().threadCounter_;
127        bundle->interpreter_ = TclThreadManager::getInstance().createNewTclInterpreter(name);
128        bundle->interpreterName_ = name;
129        bundle->running_ = true;
130        bundle->finished_ = true;
131
132        TclThreadManager::getInstance().interpreterBundles_[TclThreadManager::getInstance().threadCounter_] = bundle;
133        COUT(0) << "Created new Tcl-interpreter with ID " << TclThreadManager::getInstance().threadCounter_ << std::endl;
134        return TclThreadManager::getInstance().threadCounter_;
135    }
136
137    unsigned int TclThreadManager::createID(unsigned int threadID)
138    {
139        unsigned int temp = TclThreadManager::getInstance().threadCounter_;
140        TclThreadManager::getInstance().threadCounter_ = threadID - 1;
141        TclThreadManager::create();
142        TclThreadManager::getInstance().threadCounter_ = temp;
143        return threadID;
144    }
145
146    void TclThreadManager::destroy(unsigned int threadID)
147    {
148        TclInterpreterBundle* bundle = TclThreadManager::getInstance().getInterpreterBundle(threadID);
149        if (bundle)
150        {
151            {
152                boost::mutex::scoped_lock running_lock(bundle->runningMutex_);
153                bundle->running_ = false;
154            }
155            while (true)
156            {
157                {
158                    boost::mutex::scoped_lock finished_lock(bundle->finishedMutex_);
159                    if (bundle->finished_)
160                    {
161                        boost::mutex::scoped_lock bundles_lock(bundlesMutex_g);
162                        boost::mutex::scoped_try_lock interpreter_lock(bundle->interpreterMutex_);
163                        try
164                        {
165                            while (!interpreter_lock.try_lock())
166                            {
167                                orxonoxEvalCondition_g.notify_one();
168                                boost::this_thread::yield();
169                            }
170                        } catch (...) {}
171                        delete bundle->interpreter_;
172                        delete bundle;
173                        TclThreadManager::getInstance().interpreterBundles_.erase(threadID);
174                        break;
175                    }
176                }
177
178                orxonoxEvalCondition_g.notify_one();
179                boost::this_thread::yield();
180            }
181
182            COUT(0) << "Destroyed Tcl-interpreter with ID " << threadID << std::endl;
183        }
184    }
185
186    void TclThreadManager::execute(unsigned int threadID, const std::string& _command)
187    {
188        std::string command = stripEnclosingBraces(_command);
189
190        if (threadID == 0)
191            TclThreadManager::getInstance().pushCommandToQueue(command);
192        else
193            TclThreadManager::getInstance().pushCommandToQueue(threadID, command);
194    }
195
196    std::string TclThreadManager::query(unsigned int threadID, const std::string& command)
197    {
198        return TclThreadManager::getInstance().evalQuery(TclThreadManager::getInstance().orxonoxInterpreterBundle_->id_, threadID, command);
199    }
200
201    void TclThreadManager::status()
202    {
203        COUT(0) << "Thread ID" << '\t' << "Queue size" << '\t' << "State" << std::endl;
204
205        std::string output = "Orxonox";
206        output += "\t\t";
207        {
208            boost::mutex::scoped_lock queue_lock(TclThreadManager::getInstance().orxonoxInterpreterBundle_->queueMutex_);
209            output += getConvertedValue<unsigned int, std::string>(TclThreadManager::getInstance().orxonoxInterpreterBundle_->queue_.size());
210        }
211        output += "\t\t";
212        output += "busy";
213        COUT(0) << output << std::endl;
214
215        boost::mutex::scoped_lock bundles_lock(bundlesMutex_g);
216        for (std::map<unsigned int, TclInterpreterBundle*>::const_iterator it = TclThreadManager::getInstance().interpreterBundles_.begin(); it != TclThreadManager::getInstance().interpreterBundles_.end(); ++it)
217        {
218            std::string output = getConvertedValue<unsigned int, std::string>((*it).first);
219            output += "\t\t";
220            {
221                boost::mutex::scoped_lock queue_lock((*it).second->queueMutex_);
222                output += getConvertedValue<unsigned int, std::string>((*it).second->queue_.size());
223            }
224            output += "\t\t";
225            {
226                boost::mutex::scoped_try_lock interpreter_lock((*it).second->interpreterMutex_);
227                if (interpreter_lock.try_lock())
228                    output += "ready";
229                else
230                    output += "busy";
231            }
232            COUT(0) << output << std::endl;
233        }
234    }
235
236    void TclThreadManager::dump(unsigned int threadID)
237    {
238        TclInterpreterBundle* bundle = 0;
239        if (threadID == 0)
240        {
241            bundle = TclThreadManager::getInstance().orxonoxInterpreterBundle_;
242            COUT(0) << "Queue dump of Orxonox:" << std::endl;
243        }
244        else
245        {
246            if ((bundle = TclThreadManager::getInstance().getInterpreterBundle(threadID)))
247            {
248                COUT(0) << "Queue dump of Tcl-thread " << threadID << ":" << std::endl;
249            }
250            else
251                return;
252        }
253
254        boost::mutex::scoped_lock queue_lock(bundle->queueMutex_);
255        unsigned int index = 0;
256        for (std::list<std::string>::const_iterator it = bundle->queue_.begin(); it != bundle->queue_.end(); ++it)
257        {
258            index++;
259            COUT(0) << index << ": " << (*it) << std::endl;
260        }
261    }
262
263    void TclThreadManager::flush(unsigned int threadID)
264    {
265        TclInterpreterBundle* bundle = 0;
266        if (threadID == 0)
267            bundle = TclThreadManager::getInstance().orxonoxInterpreterBundle_;
268        else
269            if (!(bundle = TclThreadManager::getInstance().getInterpreterBundle(threadID)))
270                return;
271
272        boost::mutex::scoped_lock queue_lock(bundle->queueMutex_);
273        bundle->queue_.clear();
274        if (threadID == 0)
275        {
276            COUT(0) << "Flushed queue of Orxonox Tcl-interpreter." << std::endl;
277        }
278        else
279        {
280            COUT(0) << "Flushed queue of Tcl-interpreter " << threadID << "." << std::endl;
281        }
282    }
283
284    void TclThreadManager::tcl_execute(Tcl::object const &args)
285    {
286        TclThreadManager::getInstance().pushCommandToQueue(stripEnclosingBraces(args.get()));
287    }
288
289    std::string TclThreadManager::tcl_query(int querierID, Tcl::object const &args)
290    {
291        return TclThreadManager::getInstance().evalQuery((unsigned int)querierID, stripEnclosingBraces(args.get()));
292    }
293
294    std::string TclThreadManager::tcl_crossquery(int querierID, int threadID, Tcl::object const &args)
295    {
296        return TclThreadManager::getInstance().evalQuery((unsigned int)querierID, (unsigned int)threadID, stripEnclosingBraces(args.get()));
297    }
298
299    bool TclThreadManager::tcl_running(int threadID)
300    {
301        TclInterpreterBundle* bundle = TclThreadManager::getInstance().getInterpreterBundle((unsigned int)threadID);
302        if (bundle)
303        {
304            boost::mutex::scoped_lock running_lock(bundle->runningMutex_);
305            return bundle->running_;
306        }
307        return false;
308    }
309
310    Tcl::interpreter* TclThreadManager::createNewTclInterpreter(const std::string& threadID)
311    {
312        Tcl::interpreter* i = 0;
313        i = new Tcl::interpreter(TclBind::getInstance().getTclLibPath());
314
315        try
316        {
317            i->def("orxonox::query", TclThreadManager::tcl_query, Tcl::variadic());
318            i->def("orxonox::crossquery", TclThreadManager::tcl_crossquery, Tcl::variadic());
319            i->def("orxonox::execute", TclThreadManager::tcl_execute, Tcl::variadic());
320            i->def("orxonox::running", TclThreadManager::tcl_running);
321
322            i->def("execute", TclThreadManager::tcl_execute, Tcl::variadic());
323            i->eval("proc query args { orxonox::query " + threadID + " $args }");
324            i->eval("proc crossquery {id args} { orxonox::crossquery " + threadID + " $id $args }");
325            i->eval("set id " + threadID);
326
327            i->eval("rename exit tcl::exit");
328            i->eval("proc exit {} { orxonox TclThreadManager destroy " + threadID + " }");
329
330            i->eval("redef_puts");
331
332//            i->eval("rename while tcl::while");
333//            i->eval("proc while {test command} { tcl::while {[uplevel 1 expr $test]} {uplevel 1 $command} }"); // (\"$test\" && [orxonox::running " + threadID + "]])
334//            i->eval("rename for tcl::for");
335//            i->eval("proc for {start test next command} { uplevel tcl::for \"$start\" \"$test\" \"$next\" \"$command\" }");
336        }
337        catch (Tcl::tcl_error const &e)
338        {   COUT(1) << "Tcl error while creating Tcl-interpreter (" << threadID << "): " << e.what() << std::endl;   }
339        catch (std::exception const &e)
340        {   COUT(1) << "Error while creating Tcl-interpreter (" << threadID << "): " << e.what() << std::endl;   }
341
342        return i;
343    }
344
345    TclInterpreterBundle* TclThreadManager::getInterpreterBundle(unsigned int threadID)
346    {
347        boost::mutex::scoped_lock bundles_lock(bundlesMutex_g);
348        std::map<unsigned int, TclInterpreterBundle*>::iterator it = this->interpreterBundles_.find(threadID);
349        if (it != this->interpreterBundles_.end())
350        {
351            return (*it).second;
352        }
353        else
354        {
355            this->error("Error: No Tcl-interpreter with ID " + getConvertedValue<unsigned int, std::string>(threadID) + " existing.");
356            return 0;
357        }
358    }
359
360    Tcl::interpreter* TclThreadManager::getTclInterpreter(unsigned int threadID)
361    {
362        return this->getInterpreterBundle(threadID)->interpreter_;
363    }
364
365    std::string TclThreadManager::dumpList(const std::list<unsigned int>& list)
366    {
367        std::string output = "";
368        for (std::list<unsigned int>::const_iterator it = list.begin(); it != list.end(); ++it)
369        {
370            if (it != list.begin())
371                output += " ";
372
373            output += getConvertedValue<unsigned int, std::string>(*it);
374        }
375        return output;
376    }
377
378    void TclThreadManager::error(const std::string& error)
379    {
380        if (boost::this_thread::get_id() != threadID_g)
381        {
382            boost::mutex::scoped_lock queue_lock(this->orxonoxInterpreterBundle_->queueMutex_);
383            if (this->orxonoxInterpreterBundle_->queue_.size() >= TCLTHREADMANAGER_MAX_QUEUE_LENGTH)
384            {
385                boost::this_thread::yield();
386                return;
387            }
388        }
389
390        this->forceCommandToFrontOfQueue("error " + error);
391    }
392
393    void TclThreadManager::debug(const std::string& error)
394    {
395        if (boost::this_thread::get_id() != threadID_g)
396        {
397            boost::mutex::scoped_lock queue_lock(this->orxonoxInterpreterBundle_->queueMutex_);
398            if (this->orxonoxInterpreterBundle_->queue_.size() >= TCLTHREADMANAGER_MAX_QUEUE_LENGTH)
399            {
400                boost::this_thread::yield();
401                return;
402            }
403        }
404
405        this->forceCommandToFrontOfQueue("debug " + error);
406    }
407
408    void TclThreadManager::pushCommandToQueue(const std::string& command)
409    {
410        boost::mutex::scoped_lock queue_lock(this->orxonoxInterpreterBundle_->queueMutex_);
411        while (this->orxonoxInterpreterBundle_->queue_.size() >= TCLTHREADMANAGER_MAX_QUEUE_LENGTH)
412            fullQueueCondition_g.wait(queue_lock);
413
414        this->orxonoxInterpreterBundle_->queue_.push_back(command);
415    }
416
417    void TclThreadManager::forceCommandToFrontOfQueue(const std::string& command)
418    {
419        boost::mutex::scoped_lock queue_lock(this->orxonoxInterpreterBundle_->queueMutex_);
420        this->orxonoxInterpreterBundle_->queue_.push_front(command);
421    }
422
423    std::string TclThreadManager::popCommandFromQueue()
424    {
425        boost::mutex::scoped_lock queue_lock(this->orxonoxInterpreterBundle_->queueMutex_);
426        std::string temp = this->orxonoxInterpreterBundle_->queue_.front();
427        this->orxonoxInterpreterBundle_->queue_.pop_front();
428        fullQueueCondition_g.notify_one();
429        return temp;
430    }
431
432    bool TclThreadManager::queueIsEmpty()
433    {
434        boost::mutex::scoped_lock queue_lock(this->orxonoxInterpreterBundle_->queueMutex_);
435        return this->orxonoxInterpreterBundle_->queue_.empty();
436    }
437
438    void TclThreadManager::pushCommandToQueue(unsigned int threadID, const std::string& command)
439    {
440        TclInterpreterBundle* bundle = this->getInterpreterBundle(threadID);
441        if (bundle)
442        {
443            boost::mutex::scoped_lock queue_lock(bundle->queueMutex_);
444            if (bundle->queue_.size() >= TCLTHREADMANAGER_MAX_QUEUE_LENGTH)
445            {
446                this->error("Error: Queue of Tcl-interpreter " + getConvertedValue<unsigned int, std::string>(threadID) + " is full, couldn't add command.");
447                return;
448            }
449
450            bundle->queue_.push_back(command);
451        }
452    }
453
454    std::string TclThreadManager::popCommandFromQueue(unsigned int threadID)
455    {
456        TclInterpreterBundle* bundle = this->getInterpreterBundle(threadID);
457        if (bundle)
458        {
459            boost::mutex::scoped_lock queue_lock(bundle->queueMutex_);
460            std::string temp = bundle->queue_.front();
461            bundle->queue_.pop_front();
462            return temp;
463        }
464        return "";
465    }
466
467    bool TclThreadManager::queueIsEmpty(unsigned int threadID)
468    {
469        TclInterpreterBundle* bundle = this->getInterpreterBundle(threadID);
470        if (bundle)
471        {
472            boost::mutex::scoped_lock queue_lock(bundle->queueMutex_);
473            return bundle->queue_.empty();
474        }
475        return true;
476    }
477
478    bool TclThreadManager::updateQueriersList(TclInterpreterBundle* querier, TclInterpreterBundle* target)
479    {
480        if (querier == target)
481            return false;
482
483        boost::mutex::scoped_lock queriers_lock(target->queriersMutex_);
484
485        {
486            boost::mutex::scoped_lock queriers_lock(querier->queriersMutex_);
487            target->queriers_.insert(target->queriers_.end(), querier->queriers_.begin(), querier->queriers_.end());
488        }
489
490        target->queriers_.insert(target->queriers_.end(), querier->id_);
491
492        if (std::find(target->queriers_.begin(), target->queriers_.end(), target->id_) != target->queriers_.end())
493        {
494            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_) + ".");
495            return false;
496        }
497
498        return true;
499    }
500
501    std::string TclThreadManager::evalQuery(unsigned int querierID, const std::string& command)
502    {
503        TclInterpreterBundle* querier = this->getInterpreterBundle(querierID);
504        std::string output = "";
505        if (querier)
506        {
507            if (this->updateQueriersList(querier, this->orxonoxInterpreterBundle_))
508            {
509                boost::mutex::scoped_lock interpreter_lock(this->orxonoxInterpreterBundle_->interpreterMutex_);
510                orxonoxEvalCondition_g.wait(interpreter_lock);
511
512                if (!CommandExecutor::execute(command, false))
513                    this->error("Error: Can't execute command \"" + command + "\"!");
514
515                if (CommandExecutor::getLastEvaluation().hasReturnvalue())
516                    output = CommandExecutor::getLastEvaluation().getReturnvalue().getString();
517            }
518
519            boost::mutex::scoped_lock queriers_lock(this->orxonoxInterpreterBundle_->queriersMutex_);
520            this->orxonoxInterpreterBundle_->queriers_.clear();
521        }
522        return output;
523    }
524
525    std::string TclThreadManager::evalQuery(unsigned int querierID, unsigned int threadID, const std::string& command)
526    {
527        TclInterpreterBundle* target = 0;
528        if (threadID)
529            target = this->getInterpreterBundle(threadID);
530        else
531            target = this->orxonoxInterpreterBundle_;
532
533        std::string output = "";
534        if (target)
535        {
536            TclInterpreterBundle* querier = 0;
537            if (querierID)
538                querier = this->getInterpreterBundle(querierID);
539            else
540                querier = this->orxonoxInterpreterBundle_;
541
542            if (querier)
543            {
544                if (this->updateQueriersList(querier, target))
545                {
546                    boost::mutex::scoped_try_lock interpreter_lock(target->interpreterMutex_);
547                    bool successfullyLocked = false;
548                    try
549                    {
550                        if (querierID == 0 || std::find(querier->queriers_.begin(), querier->queriers_.end(), (unsigned int)0) != querier->queriers_.end())
551                            successfullyLocked = interpreter_lock.try_lock();
552                        else
553                        {
554                            while (!interpreter_lock.try_lock())
555                            {
556                                boost::this_thread::yield();
557                            }
558
559                            successfullyLocked = true;
560                        }
561                    } catch (...) {}
562
563                    if (successfullyLocked)
564                    {
565                        this->debug("TclThread_query: " + command);
566                        try
567                        {   output = (std::string)target->interpreter_->eval(command);   }
568                        catch (Tcl::tcl_error const &e)
569                        {   this->error("Tcl error: " + (std::string)e.what());   }
570                        catch (std::exception const &e)
571                        {   this->error("Error while executing Tcl: " + (std::string)e.what());   }
572                    }
573                    else
574                    {
575                        this->error("Error: Couldn't query Tcl-interpreter with ID " + getConvertedValue<unsigned int, std::string>(threadID) + ", interpreter is busy right now.");
576                    }
577                }
578
579                boost::mutex::scoped_lock queriers_lock(target->queriersMutex_);
580                target->queriers_.clear();
581            }
582        }
583        return output;
584    }
585
586    void TclThreadManager::update(const Clock& time)
587    {
588        {
589            orxonoxEvalCondition_g.notify_one();
590            boost::this_thread::yield();
591        }
592
593        {
594            boost::mutex::scoped_lock bundles_lock(bundlesMutex_g);
595            for (std::map<unsigned int, TclInterpreterBundle*>::iterator it = this->interpreterBundles_.begin(); it != this->interpreterBundles_.end(); ++it)
596            {
597                boost::mutex::scoped_lock queue_lock((*it).second->queueMutex_);
598                if (!(*it).second->queue_.empty())
599                {
600                    std::string command = (*it).second->queue_.front();
601                    (*it).second->queue_.pop_front();
602                    {
603                        boost::mutex::scoped_lock finished_lock((*it).second->finishedMutex_);
604                        (*it).second->finished_ = false;
605                    }
606                    boost::thread(boost::bind(&tclThread, (*it).second, command));
607                }
608            }
609        }
610
611        {
612            boost::mutex::scoped_lock interpreter_lock(this->orxonoxInterpreterBundle_->interpreterMutex_);
613            unsigned long maxtime = (unsigned long)(time.getDeltaTime() * 1000000 * TCLTHREADMANAGER_MAX_CPU_USAGE);
614            Ogre::Timer timer;
615            while (!this->queueIsEmpty())
616            {
617                CommandExecutor::execute(this->popCommandFromQueue(), false);
618                if (timer.getMicroseconds() > maxtime)
619                    break;
620            }
621        }
622    }
623
624    std::list<unsigned int> TclThreadManager::getThreadList() const
625    {
626        boost::mutex::scoped_lock bundles_lock(bundlesMutex_g);
627        std::list<unsigned int> threads;
628        for (std::map<unsigned int, TclInterpreterBundle*>::const_iterator it = this->interpreterBundles_.begin(); it != this->interpreterBundles_.end(); ++it)
629            threads.push_back((*it).first);
630        return threads;
631    }
632
633    void tclThread(TclInterpreterBundle* interpreterBundle, std::string command)
634    {
635        TclThreadManager::getInstance().debug("TclThread_execute: " + command);
636        boost::mutex::scoped_lock interpreter_lock(interpreterBundle->interpreterMutex_);
637        try
638        {
639            interpreterBundle->interpreter_->eval(command);
640        }
641        catch (Tcl::tcl_error const &e)
642        {
643            TclThreadManager::getInstance().error("Tcl (ID " + getConvertedValue<unsigned int, std::string>(interpreterBundle->id_) + ") error: " + e.what());
644        }
645        catch (std::exception const &e)
646        {
647            TclThreadManager::getInstance().error("Error while executing Tcl (ID " + getConvertedValue<unsigned int, std::string>(interpreterBundle->id_) + "): " + e.what());
648        }
649
650        boost::mutex::scoped_lock finished_lock(interpreterBundle->finishedMutex_);
651        interpreterBundle->finished_ = true;
652        interpreterBundle->finishedCondition_.notify_all();
653    }
654}
Note: See TracBrowser for help on using the repository browser.