Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/branches/core3/src/core/TclThreadManager.cc @ 1586

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

moved Debug.h, OutputHandler and OutputBuffer to util, to make COUT(x) available everywhere

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