Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

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

Merged gui branch back to trunk.

I did 2 small changes in IngameManager.cc on line 777 and 888 (yes, really), because const_reverse_iterator strangely doesn't work on MinGW.

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