Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/branches/gui/src/core/TclThreadManager.cc @ 3012

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

Renaming "tick" to "update" for all those classes not inheriting from Tickable to avoid confusions.
GameState::ticked still exists, but that's going to change anyway.

  • Property svn:eol-style set to native
File size: 26.1 KB
Line 
1/*
2 *   ORXONOX - the hottest 3D action shooter ever to exist
3 *                    > www.orxonox.net <
4 *
5 *
6 *   License notice:
7 *
8 *   This program is free software; you can redistribute it and/or
9 *   modify it under the terms of the GNU General Public License
10 *   as published by the Free Software Foundation; either version 2
11 *   of the License, or (at your option) any later version.
12 *
13 *   This program is distributed in the hope that it will be useful,
14 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
15 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16 *   GNU General Public License for more details.
17 *
18 *   You should have received a copy of the GNU General Public License
19 *   along with this program; if not, write to the Free Software
20 *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
21 *
22 *   Author:
23 *      Fabian 'x3n' Landau
24 *   Co-authors:
25 *      ...
26 *
27 */
28
29#include "TclThreadManager.h"
30
31#include <iostream>
32#include <string>
33#include <boost/thread/thread.hpp>
34#include <boost/bind.hpp>
35#include <OgreTimer.h>
36
37#include "Clock.h"
38#include "CoreIncludes.h"
39#include "ConsoleCommand.h"
40#include "CommandExecutor.h"
41#include "TclBind.h"
42#include "util/Debug.h"
43#include "util/Convert.h"
44
45
46namespace orxonox
47{
48    const unsigned int TCLTHREADMANAGER_MAX_QUEUE_LENGTH = 100;
49    const float TCLTHREADMANAGER_MAX_CPU_USAGE = 0.50f;
50
51    SetConsoleCommandShortcutAlias(TclThreadManager, execute, "tclexecute").argumentCompleter(0, autocompletion::tclthreads());
52    SetConsoleCommandShortcutAlias(TclThreadManager, query,   "tclquery"  ).argumentCompleter(0, autocompletion::tclthreads());
53    SetConsoleCommand(TclThreadManager, create,  false);
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());
57    SetConsoleCommand(TclThreadManager, status,  false);
58    SetConsoleCommand(TclThreadManager, dump,    false).argumentCompleter(0, autocompletion::tclthreads());
59    SetConsoleCommand(TclThreadManager, flush,   false).argumentCompleter(0, autocompletion::tclthreads());
60
61    TclThreadManager* TclThreadManager::singletonRef_s = 0;
62
63    TclThreadManager::TclThreadManager(Tcl::interpreter* interpreter)
64    {
65        RegisterRootObject(TclThreadManager);
66
67        assert(singletonRef_s == 0);
68        singletonRef_s = this;
69
70        this->threadCounter_ = 0;
71        this->orxonoxInterpreterBundle_.id_ = 0;
72        this->orxonoxInterpreterBundle_.interpreter_ = interpreter;
73#if (BOOST_VERSION >= 103500)
74        this->threadID_ = boost::this_thread::get_id();
75#else
76        //
77#endif
78    }
79
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
92        singletonRef_s = 0;
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())
523                    output = CommandExecutor::getLastEvaluation().getReturnvalue().getString();
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
601    void TclThreadManager::update(const Clock& time)
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
636            unsigned long maxtime = (unsigned long)(time.getDeltaTime() * 1000000 * TCLTHREADMANAGER_MAX_CPU_USAGE);
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.