Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/branches/console/src/core/TclThreadManager.cc @ 1337

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

TclThreadManager should now work with old and new versions of boost.
tested with 1_33_1, 1_34_1, 1_35_0

File size: 25.8 KB
RevLine 
[1230]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
[1257]45#define TCLTHREADMANAGER_MAX_QUEUE_LENGTH 100
[1255]46#define TCLTHREADMANAGER_MAX_CPU_USAGE 0.50
[1230]47
48namespace orxonox
49{
[1269]50    ConsoleCommandShortcutGeneric(tclexecute, createExecutor(createFunctor(&TclThreadManager::execute), "tclexecute", AccessLevel::None));
51    ConsoleCommandShortcutGeneric(tclquery,   createExecutor(createFunctor(&TclThreadManager::query),   "tclquery",   AccessLevel::None));
[1230]52    ConsoleCommand(TclThreadManager, create,    AccessLevel::None, false);
53    ConsoleCommand(TclThreadManager, destroy,   AccessLevel::None, false);
54    ConsoleCommand(TclThreadManager, execute,   AccessLevel::None, false);
55    ConsoleCommand(TclThreadManager, query,     AccessLevel::None, false);
[1269]56    ConsoleCommand(TclThreadManager, status,    AccessLevel::None, false);
57    ConsoleCommand(TclThreadManager, dump,      AccessLevel::None, false);
58    ConsoleCommand(TclThreadManager, flush,     AccessLevel::None, false);
[1230]59
[1276]60    TclThreadManager* instance_tclthreadmanager = &TclThreadManager::getInstance();
[1230]61
62    TclThreadManager::TclThreadManager()
63    {
64        RegisterRootObject(TclThreadManager);
65
[1255]66        this->threadCounter_ = 0;
67        this->orxonoxInterpreterBundle_.id_ = 0;
68        this->orxonoxInterpreterBundle_.interpreter_ = TclBind::getInstance().getTclInterpreter();
[1337]69#if (BOOST_VERSION >= 103500)
[1257]70        this->threadID_ = boost::this_thread::get_id();
[1337]71#else
72        //
73#endif
[1230]74    }
75
76    TclThreadManager& TclThreadManager::getInstance()
77    {
78        static TclThreadManager instance;
79        return instance;
80    }
81
[1255]82    unsigned int TclThreadManager::create()
[1230]83    {
[1257]84        boost::mutex::scoped_lock bundles_lock(TclThreadManager::getInstance().bundlesMutex_);
[1255]85        TclThreadManager::getInstance().threadCounter_++;
86        std::string name = getConvertedValue<unsigned int, std::string>(TclThreadManager::getInstance().threadCounter_);
[1230]87
[1255]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;
[1257]93        bundle->finished_ = true;
[1255]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_;
[1230]98    }
99
[1276]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
[1230]109    void TclThreadManager::destroy(unsigned int threadID)
110    {
[1255]111        TclInterpreterBundle* bundle = TclThreadManager::getInstance().getInterpreterBundle(threadID);
112        if (bundle)
[1230]113        {
[1255]114            {
[1257]115                boost::mutex::scoped_lock running_lock(bundle->runningMutex_);
[1255]116                bundle->running_ = false;
117            }
[1257]118            while (true)
[1255]119            {
[1257]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_);
[1337]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
[1257]130                        try
131                        {
132                            while (!interpreter_lock.try_lock())
133                            {
134                                TclThreadManager::getInstance().orxonoxEvalCondition_.notify_one();
[1337]135#if (BOOST_VERSION >= 103500)
[1257]136                                boost::this_thread::yield();
[1337]137#else
138                                boost::thread::yield();
139#endif
[1257]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();
[1337]150#if (BOOST_VERSION >= 103500)
[1257]151                boost::this_thread::yield();
[1337]152#else
153                boost::thread::yield();
154#endif
[1255]155            }
[1257]156
157            COUT(0) << "Destroyed Tcl-interpreter with ID " << threadID << std::endl;
[1230]158        }
159    }
160
[1269]161    void TclThreadManager::execute(unsigned int threadID, const std::string& _command)
[1230]162    {
[1276]163        std::string command = stripEnclosingBraces(_command);
[1269]164
165        if (threadID == 0)
166            TclThreadManager::getInstance().pushCommandToQueue(command);
167        else
168            TclThreadManager::getInstance().pushCommandToQueue(threadID, command);
[1230]169    }
170
171    std::string TclThreadManager::query(unsigned int threadID, const std::string& command)
172    {
[1255]173        return TclThreadManager::getInstance().evalQuery(TclThreadManager::getInstance().orxonoxInterpreterBundle_.id_, threadID, command);
[1230]174    }
175
[1269]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            {
[1337]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
[1269]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
[1255]263    void TclThreadManager::tcl_execute(Tcl::object const &args)
[1247]264    {
[1276]265        TclThreadManager::getInstance().pushCommandToQueue(stripEnclosingBraces(args.get()));
[1247]266    }
267
[1255]268    std::string TclThreadManager::tcl_query(int querierID, Tcl::object const &args)
[1247]269    {
[1276]270        return TclThreadManager::getInstance().evalQuery((unsigned int)querierID, stripEnclosingBraces(args.get()));
[1247]271    }
272
[1255]273    std::string TclThreadManager::tcl_crossquery(int querierID, int threadID, Tcl::object const &args)
[1230]274    {
[1276]275        return TclThreadManager::getInstance().evalQuery((unsigned int)querierID, (unsigned int)threadID, stripEnclosingBraces(args.get()));
[1230]276    }
277
[1255]278    bool TclThreadManager::tcl_running(int threadID)
[1230]279    {
[1255]280        TclInterpreterBundle* bundle = TclThreadManager::getInstance().getInterpreterBundle((unsigned int)threadID);
281        if (bundle)
[1247]282        {
[1257]283            boost::mutex::scoped_lock running_lock(bundle->runningMutex_);
[1255]284            return bundle->running_;
[1247]285        }
[1255]286        return false;
[1230]287    }
288
[1255]289    Tcl::interpreter* TclThreadManager::createNewTclInterpreter(const std::string& threadID)
[1230]290    {
[1247]291        Tcl::interpreter* i = 0;
292        i = new Tcl::interpreter(TclBind::getInstance().getTclLibPath());
[1230]293
[1247]294        try
295        {
[1255]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
[1247]309            i->eval("redef_puts");
[1255]310
[1267]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 + "]])
[1255]313//            i->eval("rename for tcl::for");
314//            i->eval("proc for {start test next command} { uplevel tcl::for \"$start\" \"$test\" \"$next\" \"$command\" }");
[1247]315        }
316        catch (Tcl::tcl_error const &e)
[1255]317        {   COUT(1) << "Tcl error while creating Tcl-interpreter (" << threadID << "): " << e.what() << std::endl;   }
[1247]318        catch (std::exception const &e)
[1255]319        {   COUT(1) << "Error while creating Tcl-interpreter (" << threadID << "): " << e.what() << std::endl;   }
[1230]320
321        return i;
322    }
323
[1255]324    TclInterpreterBundle* TclThreadManager::getInterpreterBundle(unsigned int threadID)
[1230]325    {
[1257]326        boost::mutex::scoped_lock bundles_lock(this->bundlesMutex_);
[1255]327        std::map<unsigned int, TclInterpreterBundle*>::iterator it = this->interpreterBundles_.find(threadID);
328        if (it != this->interpreterBundles_.end())
[1230]329        {
[1255]330            return (*it).second;
[1230]331        }
[1255]332        else
[1230]333        {
[1257]334            this->error("Error: No Tcl-interpreter with ID " + getConvertedValue<unsigned int, std::string>(threadID) + " existing.");
[1255]335            return 0;
[1230]336        }
337    }
338
[1255]339    std::string TclThreadManager::dumpList(const std::list<unsigned int>& list)
[1230]340    {
[1255]341        std::string output = "";
342        for (std::list<unsigned int>::const_iterator it = list.begin(); it != list.end(); ++it)
[1230]343        {
[1255]344            if (it != list.begin())
345                output += " ";
[1230]346
[1255]347            output += getConvertedValue<unsigned int, std::string>(*it);
[1230]348        }
[1255]349        return output;
[1230]350    }
351
[1257]352    void TclThreadManager::error(const std::string& error)
353    {
[1337]354#if (BOOST_VERSION >= 103500)
[1257]355        if (boost::this_thread::get_id() != this->threadID_)
[1337]356#else
357        if (boost::thread() != this->threadID_)
358#endif
[1257]359        {
360            boost::mutex::scoped_lock queue_lock(this->orxonoxInterpreterBundle_.queueMutex_);
361            if (this->orxonoxInterpreterBundle_.queue_.size() >= TCLTHREADMANAGER_MAX_QUEUE_LENGTH)
[1258]362            {
[1337]363#if (BOOST_VERSION >= 103500)
[1258]364                boost::this_thread::yield();
[1337]365#else
366                boost::thread::yield();
367#endif
[1257]368                return;
[1258]369            }
[1257]370        }
371
372        this->forceCommandToFrontOfQueue("error " + error);
373    }
374
[1276]375    void TclThreadManager::debug(const std::string& error)
376    {
[1337]377#if (BOOST_VERSION >= 103500)
[1276]378        if (boost::this_thread::get_id() != this->threadID_)
[1337]379#else
380        if (boost::thread() != this->threadID_)
381#endif
[1276]382        {
383            boost::mutex::scoped_lock queue_lock(this->orxonoxInterpreterBundle_.queueMutex_);
384            if (this->orxonoxInterpreterBundle_.queue_.size() >= TCLTHREADMANAGER_MAX_QUEUE_LENGTH)
385            {
[1337]386#if (BOOST_VERSION >= 103500)
[1276]387                boost::this_thread::yield();
[1337]388#else
389                boost::thread::yield();
390#endif
[1276]391                return;
392            }
393        }
394
395        this->forceCommandToFrontOfQueue("debug " + error);
396    }
397
[1255]398    void TclThreadManager::pushCommandToQueue(const std::string& command)
[1247]399    {
[1257]400        boost::mutex::scoped_lock queue_lock(this->orxonoxInterpreterBundle_.queueMutex_);
[1255]401        while (this->orxonoxInterpreterBundle_.queue_.size() >= TCLTHREADMANAGER_MAX_QUEUE_LENGTH)
[1257]402            this->fullQueueCondition_.wait(queue_lock);
[1255]403
404        this->orxonoxInterpreterBundle_.queue_.push_back(command);
[1247]405    }
406
[1255]407    void TclThreadManager::forceCommandToFrontOfQueue(const std::string& command)
[1247]408    {
[1257]409        boost::mutex::scoped_lock queue_lock(this->orxonoxInterpreterBundle_.queueMutex_);
[1255]410        this->orxonoxInterpreterBundle_.queue_.push_front(command);
[1247]411    }
412
[1255]413    std::string TclThreadManager::popCommandFromQueue()
[1230]414    {
[1257]415        boost::mutex::scoped_lock queue_lock(this->orxonoxInterpreterBundle_.queueMutex_);
[1255]416        std::string temp = this->orxonoxInterpreterBundle_.queue_.front();
417        this->orxonoxInterpreterBundle_.queue_.pop_front();
418        this->fullQueueCondition_.notify_one();
419        return temp;
[1230]420    }
421
[1255]422    bool TclThreadManager::queueIsEmpty()
[1230]423    {
[1257]424        boost::mutex::scoped_lock queue_lock(this->orxonoxInterpreterBundle_.queueMutex_);
[1255]425        return this->orxonoxInterpreterBundle_.queue_.empty();
[1230]426    }
427
[1255]428    void TclThreadManager::pushCommandToQueue(unsigned int threadID, const std::string& command)
[1230]429    {
[1255]430        TclInterpreterBundle* bundle = this->getInterpreterBundle(threadID);
431        if (bundle)
432        {
[1257]433            boost::mutex::scoped_lock queue_lock(bundle->queueMutex_);
[1255]434            if (bundle->queue_.size() >= TCLTHREADMANAGER_MAX_QUEUE_LENGTH)
435            {
[1257]436                this->error("Error: Queue of Tcl-interpreter " + getConvertedValue<unsigned int, std::string>(threadID) + " is full, couldn't add command.");
[1255]437                return;
438            }
[1230]439
[1255]440            bundle->queue_.push_back(command);
441        }
[1230]442    }
443
[1255]444    std::string TclThreadManager::popCommandFromQueue(unsigned int threadID)
[1230]445    {
[1255]446        TclInterpreterBundle* bundle = this->getInterpreterBundle(threadID);
447        if (bundle)
[1230]448        {
[1257]449            boost::mutex::scoped_lock queue_lock(bundle->queueMutex_);
[1255]450            std::string temp = bundle->queue_.front();
451            bundle->queue_.pop_front();
452            return temp;
[1230]453        }
[1255]454        return "";
[1230]455    }
456
[1255]457    bool TclThreadManager::queueIsEmpty(unsigned int threadID)
[1230]458    {
[1255]459        TclInterpreterBundle* bundle = this->getInterpreterBundle(threadID);
460        if (bundle)
[1230]461        {
[1257]462            boost::mutex::scoped_lock queue_lock(bundle->queueMutex_);
[1255]463            return bundle->queue_.empty();
[1230]464        }
[1255]465        return true;
[1230]466    }
467
[1255]468    bool TclThreadManager::updateQueriersList(TclInterpreterBundle* querier, TclInterpreterBundle* target)
[1230]469    {
[1255]470        if (querier == target)
471            return false;
[1230]472
[1257]473        boost::mutex::scoped_lock queriers_lock(target->queriersMutex_);
[1255]474
[1230]475        {
[1257]476            boost::mutex::scoped_lock queriers_lock(querier->queriersMutex_);
[1255]477            target->queriers_.insert(target->queriers_.end(), querier->queriers_.begin(), querier->queriers_.end());
[1230]478        }
[1255]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())
[1230]483        {
[1257]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_) + ".");
[1255]485            return false;
[1230]486        }
[1255]487
488        return true;
[1230]489    }
490
[1255]491    std::string TclThreadManager::evalQuery(unsigned int querierID, const std::string& command)
[1230]492    {
[1255]493        TclInterpreterBundle* querier = this->getInterpreterBundle(querierID);
494        std::string output = "";
495        if (querier)
496        {
497            if (this->updateQueriersList(querier, &this->orxonoxInterpreterBundle_))
498            {
[1337]499#if (BOOST_VERSION >= 103500)
[1257]500                boost::mutex::scoped_lock interpreter_lock(this->orxonoxInterpreterBundle_.interpreterMutex_);
[1337]501#else
502                boost::try_mutex::scoped_lock interpreter_lock(this->orxonoxInterpreterBundle_.interpreterMutex_);
503#endif
[1257]504                this->orxonoxEvalCondition_.wait(interpreter_lock);
[1230]505
[1255]506                if (!CommandExecutor::execute(command, false))
[1257]507                    this->error("Error: Can't execute command \"" + command + "\"!");
[1230]508
[1255]509                if (CommandExecutor::getLastEvaluation().hasReturnvalue())
510                    output = CommandExecutor::getLastEvaluation().getReturnvalue().toString();
511            }
[1230]512
[1257]513            boost::mutex::scoped_lock queriers_lock(this->orxonoxInterpreterBundle_.queriersMutex_);
[1255]514            this->orxonoxInterpreterBundle_.queriers_.clear();
515        }
516        return output;
[1230]517    }
518
[1255]519    std::string TclThreadManager::evalQuery(unsigned int querierID, unsigned int threadID, const std::string& command)
[1230]520    {
[1257]521        TclInterpreterBundle* target = 0;
522        if (threadID)
523            target = this->getInterpreterBundle(threadID);
524        else
525            target = &this->orxonoxInterpreterBundle_;
526
[1255]527        std::string output = "";
528        if (target)
[1247]529        {
[1255]530            TclInterpreterBundle* querier = 0;
531            if (querierID)
532                querier = this->getInterpreterBundle(querierID);
533            else
534                querier = &this->orxonoxInterpreterBundle_;
[1230]535
[1255]536            if (querier)
[1230]537            {
[1255]538                if (this->updateQueriersList(querier, target))
[1230]539                {
[1337]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
[1255]545                    bool successfullyLocked = false;
[1247]546                    try
547                    {
[1255]548                        if (querierID == 0 || std::find(querier->queriers_.begin(), querier->queriers_.end(), (unsigned int)0) != querier->queriers_.end())
[1257]549                            successfullyLocked = interpreter_lock.try_lock();
[1255]550                        else
551                        {
[1257]552                            while (!interpreter_lock.try_lock())
[1337]553                            {
554#if (BOOST_VERSION >= 103500)
[1255]555                                boost::this_thread::yield();
[1337]556#else
557                                boost::thread::yield();
558#endif
559                            }
[1255]560
561                            successfullyLocked = true;
562                        }
563                    } catch (...) {}
564
565                    if (successfullyLocked)
[1247]566                    {
[1276]567                        this->debug("TclThread_query: " + command);
[1255]568                        try
569                        {   output = (std::string)target->interpreter_->eval(command);   }
570                        catch (Tcl::tcl_error const &e)
[1257]571                        {   this->error("Tcl error: " + (std::string)e.what());   }
[1255]572                        catch (std::exception const &e)
[1257]573                        {   this->error("Error while executing Tcl: " + (std::string)e.what());   }
[1247]574                    }
[1255]575                    else
[1247]576                    {
[1257]577                        this->error("Error: Couldn't query Tcl-interpreter with ID " + getConvertedValue<unsigned int, std::string>(threadID) + ", interpreter is busy right now.");
[1247]578                    }
[1230]579                }
[1255]580
[1257]581                boost::mutex::scoped_lock queriers_lock(target->queriersMutex_);
[1255]582                target->queriers_.clear();
[1230]583            }
584        }
[1255]585        return output;
[1230]586    }
587
588    void TclThreadManager::tick(float dt)
589    {
590        {
[1255]591            this->orxonoxEvalCondition_.notify_one();
[1337]592#if (BOOST_VERSION >= 103500)
[1255]593            boost::this_thread::yield();
[1337]594#else
595            boost::thread::yield();
596#endif
[1230]597        }
598
599        {
[1257]600            boost::mutex::scoped_lock bundles_lock(this->bundlesMutex_);
[1255]601            for (std::map<unsigned int, TclInterpreterBundle*>::iterator it = this->interpreterBundles_.begin(); it != this->interpreterBundles_.end(); ++it)
[1230]602            {
[1257]603                boost::mutex::scoped_lock queue_lock((*it).second->queueMutex_);
[1255]604                if (!(*it).second->queue_.empty())
[1230]605                {
[1255]606                    std::string command = (*it).second->queue_.front();
607                    (*it).second->queue_.pop_front();
[1247]608                    {
[1257]609                        boost::mutex::scoped_lock finished_lock((*it).second->finishedMutex_);
[1255]610                        (*it).second->finished_ = false;
[1247]611                    }
[1255]612                    boost::thread(boost::bind(&tclThread, (*it).second, command));
[1230]613                }
[1247]614            }
615        }
616
617        {
[1337]618#if (BOOST_VERSION >= 103500)
[1257]619            boost::mutex::scoped_lock interpreter_lock(this->orxonoxInterpreterBundle_.interpreterMutex_);
[1337]620#else
621            boost::try_mutex::scoped_lock interpreter_lock(this->orxonoxInterpreterBundle_.interpreterMutex_);
622#endif
[1255]623            unsigned long maxtime = (unsigned long)(dt * 1000000 * TCLTHREADMANAGER_MAX_CPU_USAGE);
624            Ogre::Timer timer;
625            while (!this->queueIsEmpty())
[1247]626            {
[1255]627                CommandExecutor::execute(this->popCommandFromQueue(), false);
628                if (timer.getMicroseconds() > maxtime)
629                    break;
[1230]630            }
[1255]631        }
632    }
[1230]633
[1255]634    void tclThread(TclInterpreterBundle* interpreterBundle, std::string command)
635    {
[1276]636        TclThreadManager::getInstance().debug("TclThread_execute: " + command);
[1337]637#if (BOOST_VERSION >= 103500)
[1257]638        boost::mutex::scoped_lock interpreter_lock(interpreterBundle->interpreterMutex_);
[1337]639#else
640        boost::try_mutex::scoped_lock interpreter_lock(interpreterBundle->interpreterMutex_);
641#endif
[1255]642        try
643        {
644            interpreterBundle->interpreter_->eval(command);
645        }
646        catch (Tcl::tcl_error const &e)
647        {
[1257]648            TclThreadManager::getInstance().error("Tcl (ID " + getConvertedValue<unsigned int, std::string>(interpreterBundle->id_) + ") error: " + e.what());
[1255]649        }
650        catch (std::exception const &e)
651        {
[1257]652            TclThreadManager::getInstance().error("Error while executing Tcl (ID " + getConvertedValue<unsigned int, std::string>(interpreterBundle->id_) + "): " + e.what());
[1255]653        }
654
[1257]655        boost::mutex::scoped_lock finished_lock(interpreterBundle->finishedMutex_);
[1255]656        interpreterBundle->finished_ = true;
657        interpreterBundle->finishedCondition_.notify_all();
[1230]658    }
659}
Note: See TracBrowser for help on using the repository browser.