Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/archive/lod/src/core/TclThreadManager.cc @ 12397

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

Changed initialisation of TclThreadManager, TclBind and Shell to match the simple singleton concept (runtime assert in the c'tor).
That simplifies things a lot. The instances now 'belong' to GSRoot.

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