Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/branches/core4/src/core/TclThreadManager.cc @ 3246

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

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