Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/trunk/src/core/TclThreadManager.cc @ 1786

Last change on this file since 1786 was 1786, checked in by rgrieder, 16 years ago

Corrected types when using 'const Type' constants

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