Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/branches/core3/src/core/TclThreadManager.cc @ 1915

Last change on this file since 1915 was 1728, checked in by landauf, 16 years ago

Added getXXX() functions to MultiType, where XXX stands for any supported typename.
getString() replaces toString().
Like in getValue(type* pointer), the current value gets converted to the requested type. It's basically just a call to the convert-operator, so (1) "type a = mymultitype;", (2) "type a; mymultitype.getValue(&a);" and (3) "type a = get'Type'();" are equivalent, but the implicit cast (1) may be ambiguous.

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