Changeset 15073 for trunk


Ignore:
Timestamp:
03/15/13 12:19:59 (12 years ago)
Author:
tbretz
Message:
Implemented v8::timeout and let dim.getDescription return an object of type Description; some improvements to the exception handling of the java console, which ensures that (hopefully) all exceptions are handled and printed and that all of them are catched before the next execution; make sure that all threads are stopped before the return to the command line prompt; made the bahaviour of dim.wait more intuitive; fixed a bug which caused the thread-ids to be not correctly removed from the list after a thread terminated
Location:
trunk/FACT++/src
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/FACT++/src/InterpreterV8.cc

    r15046 r15073  
    3434v8::Handle<v8::FunctionTemplate> InterpreterV8::fTemplateSky;
    3535v8::Handle<v8::FunctionTemplate> InterpreterV8::fTemplateEvent;
     36v8::Handle<v8::FunctionTemplate> InterpreterV8::fTemplateDescription;
    3637//v8::Handle<v8::FunctionTemplate> InterpreterV8::fTemplateDatabase;
    3738
     
    129130}
    130131
     132Handle<Value> InterpreterV8::FuncTimeout(const Arguments &args)
     133{
     134    if (args.Length()<2)
     135        return ThrowException(String::New("Number of arguments must be at least two."));
     136
     137    if (!args[0]->IsNull() && !args[0]->IsInt32())
     138        return ThrowException(String::New("Argument 0 not null and not an int32."));
     139
     140    if (!args[1]->IsFunction())
     141        return ThrowException(String::New("Argument 1 not a function."));
     142
     143    const int32_t timeout = args[0]->IsNull() ? 0 : args[0]->Int32Value();
     144    const bool    null    = args[0]->IsNull();
     145
     146    HandleScope handle_scope;
     147
     148    TryCatch exception;
     149
     150    const Handle<Script> sleep = Script::Compile(String::New("v8.sleep();"), String::New("internal"));
     151    if (sleep.IsEmpty())
     152        return Undefined();
     153
     154    Handle<Function> func = Handle<Function>::Cast(args[1]);
     155
     156    Handle<Value> argv[args.Length()-2];
     157    for (int i=0; i<args.Length()-2; i++)
     158        argv[i] = args[i+2];
     159
     160    Time t;
     161    while (!exception.HasCaught())
     162    {
     163        const Handle<Value> rc = func->Call(func, args.Length()-2, argv);
     164        if (!rc->IsUndefined())
     165            return rc;
     166
     167        if (!null && Time()-t>=boost::posix_time::milliseconds(abs(timeout)))
     168            break;
     169
     170        // We cannot sleep directly because we have to give control back to
     171        // JavaScript ever now and then. This also allows us to catch
     172        // exceptions, either from the preemption or ConvertEvent
     173        sleep->Run();
     174    }
     175
     176    if (exception.HasCaught())
     177        return exception.ReThrow();
     178
     179    if (timeout<0)
     180        return Undefined();
     181
     182    const string str = "Waiting for func to return a defined value timed out.";
     183    return ThrowException(String::New(str.c_str()));
     184}
     185
    131186void InterpreterV8::Thread(int &id, Persistent<Function> func, uint32_t ms)
    132187{
     
    139194    }
    140195
    141     id = V8::GetCurrentThreadId();
    142     fThreadIds.insert(id);
     196    // Warning: As soon as id is set, the parent of this thread might terminate
     197    //          and hance the reference to id does not exist anymore. So, id
     198    //          is just a kind of return value and must not be used at all
     199    //          otherwise.
     200
     201    const int id_local = V8::GetCurrentThreadId();
     202    id = id_local;
     203    fThreadIds.insert(id_local);
    143204
    144205    const HandleScope handle_scope;
     
    153214
    154215    func.Dispose();
    155     fThreadIds.erase(id);
     216    fThreadIds.erase(id_local);
    156217
    157218    if (!HandleException(exception, "thread"))
     
    485546            break;
    486547
     548    if (is==services.end())
     549        return Undefined();
     550
    487551    HandleScope handle_scope;
    488552
    489     Handle<Array> arr = Array::New();
     553    Handle<Object> arr = fTemplateDescription->GetFunction()->NewInstance();//Object::New();
    490554    if (arr.IsEmpty())
    491555        return Undefined();
     
    511575            return Undefined();
    512576
    513         obj->Set(String::New("name"), String::New(it->name.c_str()), ReadOnly);
     577        if (!it->name.empty())
     578            obj->Set(String::New("name"), String::New(it->name.c_str()), ReadOnly);
    514579        if (!it->comment.empty())
    515580            obj->Set(String::New("description"), String::New(it->comment.c_str()), ReadOnly);
     
    628693            return ThrowException(String::New("File name missing"));
    629694
    630         if (!ExecuteFile(*file))
     695        TryCatch exception;
     696        const bool rc = ExecuteFile(*file);
     697        if (exception.HasCaught())
     698            HandleException(exception, "include");
     699        if (!rc)
    631700        {
    632701            V8::TerminateExecution(fThreadId);
     
    11451214        return Undefined();
    11461215
    1147     //const Handle<String> data   = String::New("data");
     1216    const Handle<String> data   = String::New("data");
    11481217    const Handle<String> object = String::New("obj");
    11491218
     
    11681237            {
    11691238                if (!named)
    1170                     return handle_scope.Close(val);
    1171 
    1172                 const Handle<Object> event = val->ToObject();
    1173                 const Handle<Value>  obj   = event->Get(object);
    1174 
    1175                 if (!obj.IsEmpty() && obj->IsObject())
    11761239                {
    1177                     // Has names and data was received?
    1178                     if (obj->ToObject()->GetOwnPropertyNames()->Length()>0)
     1240                    const Handle<Object> event = val->ToObject();
     1241                    const Handle<Value>  obj   = event->Get(data);
     1242
     1243                    // No names (no 'obj'), but 'data'
     1244                    if (!obj.IsEmpty() && !obj->IsUndefined())
    11791245                        return handle_scope.Close(val);
     1246                }
     1247                else
     1248                {
     1249                    const Handle<Object> event = val->ToObject();
     1250                    const Handle<Value>  obj   = event->Get(object);
     1251
     1252                    if (!obj.IsEmpty() && obj->IsObject())
     1253                    {
     1254                        // Has names and data was received?
     1255                        if (obj->ToObject()->GetOwnPropertyNames()->Length()>0)
     1256                            return handle_scope.Close(val);
     1257                    }
    11801258                }
    11811259            }
     
    18731951
    18741952    // maybe skip: "    at internal:"
     1953    // maybe skip: "    at unknown source:"
    18751954
    18761955    auto it = tokenizer.begin();
     
    19151994
    19161995    const Handle<Value> result = script->Run();
    1917 
    19181996    if (exception.HasCaught())
    19191997    {
     
    19572035bool InterpreterV8::ExecuteConsole()
    19582036{
     2037    // Just necessray for the Handle<Script>
     2038    const HandleScope handle_scope;
     2039
     2040    // A void script doing nothing than making sure that some JavaScript is executed
     2041    const Handle<Script> catcher = Script::Compile(String::New(";"), String::New(""));
     2042
     2043    // Unlocking is necessary for the preemption to work
     2044    const Unlocker global_unlock;
     2045
    19592046    JsSetState(3);
    19602047
     
    19652052
    19662053    string command;
    1967 
    19682054    while (1)
    19692055    {
     
    19902076        }
    19912077
     2078        // Locking is necessary to be able to execute java script code
     2079        const Locker lock;
     2080
     2081        // Dump all pending exceptions. This is mainly to catch the 'null' exception
     2082        // thrown if a running JavaScript should be terminated from somewhere.
     2083        while (1)
     2084        {
     2085            TryCatch exception;
     2086            catcher->Run();
     2087            if (!exception.HasCaught())
     2088                break;
     2089        }
     2090
    19922091        // Catch exceptions during code compilation
    19932092        TryCatch exception;
    19942093
    19952094        // Execute code which was entered
    1996         bool rc = ExecuteCode(command, "", false).IsEmpty();
     2095        bool rc = ExecuteCode(command, "console", false).IsEmpty();
    19972096        if (exception.HasCaught())
    19982097        {
     
    20002099            rc = true;
    20012100        }
     2101
     2102        // Stop all other threads
     2103        for (auto it=fThreadIds.begin(); it!=fThreadIds.end(); it++)
     2104            V8::TerminateExecution(*it);
     2105
     2106        // Allow the java scripts (threads) to run and hence to terminate
     2107        const Unlocker unlock;
     2108
     2109        // Wait until all threads are terminated
     2110        while (fThreadIds.size()>0)
     2111            usleep(1000);
    20022112
    20032113        // In case of an exception add an empty line to the output
     
    21452255    Handle<ObjectTemplate> v8 = ObjectTemplate::New();
    21462256    v8->Set(String::New("sleep"),   FunctionTemplate::New(WrapSleep), ReadOnly);
     2257    v8->Set(String::New("timeout"), FunctionTemplate::New(WrapTimeout), ReadOnly);
    21472258    v8->Set(String::New("version"), String::New(V8::GetVersion()),    ReadOnly);
    21482259
     
    21842295    global->Set(String::New("Event"), evt, ReadOnly);
    21852296
     2297    Handle<FunctionTemplate> desc = FunctionTemplate::New();
     2298    desc->SetClassName(String::New("Description"));
     2299    global->Set(String::New("Description"), desc, ReadOnly);
     2300
    21862301    fTemplateEvent = evt;
     2302    fTemplateDescription = desc;
    21872303
    21882304#ifdef HAVE_NOVA
  • trunk/FACT++/src/InterpreterV8.h

    r15046 r15073  
    5050    static v8::Handle<v8::FunctionTemplate> fTemplateSky;
    5151    static v8::Handle<v8::FunctionTemplate> fTemplateEvent;
     52    static v8::Handle<v8::FunctionTemplate> fTemplateDescription;
    5253
    5354#ifdef HAVE_SQL
     
    6768    v8::Handle<v8::Value> FuncSend(const v8::Arguments& args);
    6869    v8::Handle<v8::Value> FuncSleep(const v8::Arguments& args);
     70    v8::Handle<v8::Value> FuncTimeout(const v8::Arguments& args);
    6971    v8::Handle<v8::Value> FuncThread(const v8::Arguments& args);
    7072    v8::Handle<v8::Value> FuncKill(const v8::Arguments& args);
     
    124126    static v8::Handle<v8::Value> WrapSend(const v8::Arguments &args)     { if (This) return This->FuncSend(args);     else return v8::Undefined(); }
    125127    static v8::Handle<v8::Value> WrapSleep(const v8::Arguments &args)    { if (This) return This->FuncSleep(args);    else return v8::Undefined(); }
     128    static v8::Handle<v8::Value> WrapTimeout(const v8::Arguments &args)  { if (This) return This->FuncTimeout(args);  else return v8::Undefined(); }
    126129    static v8::Handle<v8::Value> WrapThread(const v8::Arguments &args)   { if (This) return This->FuncThread(args);   else return v8::Undefined(); }
    127130    static v8::Handle<v8::Value> WrapKill(const v8::Arguments &args)     { if (This) return This->FuncKill(args);     else return v8::Undefined(); }
Note: See TracChangeset for help on using the changeset viewer.