Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

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

f* svn: It doesn't even inform you if you attempt to set a non existing property. It is svn:eol-style and not eol-style when using the command by the way…

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