Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/branches/network/src/core/TclThreadManager.cc @ 1464

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

merged console branch into network branch

after several heavy troubles it compiles, but there is still a bug I couldn't fix: orxonox crashes as soon as one presses a key after opening the console… maybe someone else sees the problem?

File size: 26.4 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.