Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

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

merged core3 back to trunk

  • 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.