Changeset 14598
- Timestamp:
- 11/10/12 12:16:14 (12 years ago)
- Location:
- trunk/FACT++/src
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/FACT++/src/InterpreterV8.cc
r14591 r14598 1 1 #include "InterpreterV8.h" 2 3 #ifdef HAVE_V8 4 5 #include <fstream> 6 #include <sstream> 7 #include <iomanip> 8 9 #include <boost/tokenizer.hpp> 2 10 3 11 #ifdef HAVE_NOVA … … 10 18 #endif 11 19 12 #include <boost/tokenizer.hpp>13 14 InterpreterV8 *InterpreterV8::This = 0;15 16 #ifdef HAVE_V817 18 20 #include <v8.h> 19 #include <fstream>20 #include <sstream>21 #include <iomanip>22 21 23 22 using namespace std; … … 29 28 // ========================================================================== 30 29 30 void InterpreterV8::Terminate() 31 { 32 for (auto it=fThreadIds.begin(); it!=fThreadIds.end(); it++) 33 V8::TerminateExecution(*it); 34 fThreadIds.clear(); 35 36 if (fThreadId>=0) 37 V8::TerminateExecution(fThreadId); 38 } 39 31 40 Handle<Value> InterpreterV8::FuncExit(const Arguments &) 32 41 { 33 V8::TerminateExecution(fThreadId);42 Terminate(); 34 43 return ThrowException(String::New("exit")); 35 /* 36 if (args.Length()!=1) 37 return ThrowException(String::New("Number of arguments must be exactly 1.")); 38 39 if (!args[0]->IsUint32()) 40 return ThrowException(String::New("Argument 1 must be an uint32.")); 41 42 const HandleScope handle_scope; 43 44 JsSleep(args[0]->Int32Value()); 45 */ 46 return Undefined(); 47 } 48 44 } 49 45 50 46 Handle<Value> InterpreterV8::FuncSleep(const Arguments& args) … … 77 73 78 74 const Handle<Script> script = Script::Compile(String::New(code.c_str())); 75 if (script.IsEmpty()) 76 return Undefined(); 79 77 80 78 return handle_scope.Close(script->Run()); … … 82 80 //JsSleep(args[0]->Int32Value()); 83 81 //return Undefined(); 82 } 83 84 void InterpreterV8::ThreadTimeout(Persistent<Function> func, uint32_t ms) 85 { 86 if (fThreadId<0) 87 return; 88 89 Locker lock; 90 91 const HandleScope handle_scope; 92 93 fGlobalContext->Enter(); 94 95 const int id = V8::GetCurrentThreadId(); 96 fThreadIds.insert(id); 97 98 TryCatch exception; 99 100 const Handle<Script> sleep = Script::Compile(String::New(("dim.sleep("+to_string(ms)+");").c_str())); 101 if (!sleep.IsEmpty() && !sleep->Run().IsEmpty()) 102 { 103 Handle<Value> args[] = { }; 104 func->Call(func, 0, args); 105 } 106 107 func.Dispose(); 108 fThreadIds.erase(id); 109 110 if (!exception.HasCaught()) 111 return; 112 113 ReportException(&exception); 114 Terminate(); 115 } 116 117 Handle<Value> InterpreterV8::FuncTimeout(const Arguments& args) 118 { 119 if (args.Length()!=2) 120 return ThrowException(String::New("Number of arguments must be at least 1.")); 121 122 if (args.Length()==0) 123 return ThrowException(String::New("Number of arguments must be at least 1.")); 124 125 if (!args[1]->IsFunction()) 126 return ThrowException(String::New("Argument 1 not a function.")); 127 128 if (!args[0]->IsUint32()) 129 return ThrowException(String::New("Argument 0 not an uint32.")); 130 131 Handle<Function> handle = Handle<Function>::Cast(args[1]); 132 133 Persistent<Function> func = Persistent<Function>::New(handle); 134 135 const uint32_t ms = args[0]->Uint32Value(); 136 137 fTimeout.push_back(thread(bind(&InterpreterV8::ThreadTimeout, this, func, ms))); 138 return Undefined(); 84 139 } 85 140 … … 173 228 174 229 const Handle<Script> script = Script::Compile(String::New(code.c_str())); 175 const Handle<Value> result = script->Run(); 230 if (script.IsEmpty()) 231 return Undefined(); 232 233 const Handle<Value> result = script->Run(); 176 234 177 235 return exception.HasCaught() ? exception.ReThrow() : handle_scope.Close(result); … … 210 268 HandleScope handle_scope; 211 269 212 // It is important to catch the exception thrown213 // by Date::New in case of thread termination!214 Local<Value> date;215 {216 TryCatch exception;217 date = Date::New(rc.time.JavaDate());218 if (exception.HasCaught())219 return exception.ReThrow();220 }221 222 270 Handle<ObjectTemplate> obj = ObjectTemplate::New(); 223 271 obj->Set(String::New("index"), rc.index<=-256?Undefined():Integer::New(rc.index), ReadOnly); 224 272 obj->Set(String::New("name"), rc.index<=-256?Undefined():String::New(rc.name.c_str()), ReadOnly); 225 if (rc.index>-256) 273 274 const Local<Value> date = Date::New(rc.time.JavaDate()); 275 if (rc.index>-256 && !date.IsEmpty()) 226 276 obj->Set(String::New("time"), date); 277 227 278 //obj->Set(String::New("toString"), String::New(("[Object state "+string(*str)+":"+to_string(rc.index)+"]").c_str())); 228 279 … … 380 431 HandleScope handle_scope; 381 432 382 void *ptr = Handle<External>::Cast(args.This()->GetInternalField(0))->Value();433 void *ptr = External::Unwrap(args.This()->GetInternalField(0)); 383 434 if (!ptr) 384 435 return handle_scope.Close(Boolean::New(false)); … … 402 453 HandleScope handle_scope; 403 454 404 void *ptr = Handle<External>::Cast(args.This()->GetInternalField(0))->Value();455 void *ptr = External::Unwrap(args.This()->GetInternalField(0)); 405 456 if (!ptr) 406 457 return Undefined(); … … 419 470 420 471 Handle<Array> ret = Array::New(); 472 if (ret.IsEmpty()) 473 return Undefined(); 474 421 475 ret->Set(String::New("table"), String::New(res.table()), ReadOnly); 422 476 ret->Set(String::New("query"), String::New(query.c_str()), ReadOnly); 423 477 424 478 Handle<Array> cols = Array::New(); 479 if (cols.IsEmpty()) 480 return Undefined(); 425 481 426 482 int irow=0; … … 428 484 { 429 485 Handle<Array> row = Array::New(); 486 if (row.IsEmpty()) 487 return Undefined(); 430 488 431 489 const mysqlpp::FieldNames *list = it->field_list().list; … … 518 576 // It is important to catch the exception thrown 519 577 // by Date::New in case of thread termination! 520 TryCatch exception; 521 Local<Value> val = Date::New(date*1000); 522 if (exception.HasCaught()) 523 return exception.ReThrow(); 524 //if (V8::IsExecutionTerminating()) 525 // return Undefined(); 578 const Local<Value> val = Date::New(date*1000); 579 if (val.IsEmpty()) 580 return Undefined(); 526 581 527 582 row->Set(name, val, ReadOnly); … … 570 625 571 626 Handle<Object> obj = tem->NewInstance(); 627 if (obj.IsEmpty()) 628 return Undefined(); 629 572 630 obj->SetInternalField(0, External::New(db)); 573 631 … … 640 698 Handle<Value> InterpreterV8::ConvertEvent(const EventImp *evt, uint64_t counter, const char *str) 641 699 { 642 Local<Value> date;643 644 // It is important to catch the exception thrown645 // by Date::New in case of thread termination!646 {647 TryCatch exception;648 date = Date::New(evt->GetJavaDate());649 if (exception.HasCaught())650 return exception.ReThrow();651 }652 653 700 const vector<Description> vec = JsDescription(str); 654 701 655 702 Handle<Array> ret = Array::New(); 703 if (ret.IsEmpty()) 704 return Undefined(); 705 706 const Local<Value> date = Date::New(evt->GetJavaDate()); 707 if (date.IsEmpty()) 708 return Undefined(); 709 656 710 ret->Set(String::New("name"), String::New(str), ReadOnly); 657 711 ret->Set(String::New("format"), String::New(evt->GetFormat().c_str()), ReadOnly); … … 660 714 ret->Set(String::New("size"), Integer::New(evt->GetSize()), ReadOnly); 661 715 ret->Set(String::New("counter"), Integer::New(counter), ReadOnly); 662 ret->Set(String::New("time"), date,ReadOnly);716 ret->Set(String::New("time"), date, ReadOnly); 663 717 664 718 // If no event was received (usually a disconnection event in … … 681 735 682 736 Handle<Array> obj = tok.size()>1 ? Array::New() : ret; 737 if (obj.IsEmpty()) 738 return Undefined(); 683 739 684 740 const char *ptr = evt->GetText(); … … 716 772 { 717 773 Handle<Array> a = Array::New(cnt); 774 if (a.IsEmpty()) 775 return Undefined(); 776 718 777 for (uint32_t i=0; i<cnt; i++) 719 778 a->Set(i, Convert(type, ptr)); … … 774 833 775 834 const Handle<Script> sleep = Script::Compile(String::New("dim.sleep();")); 835 if (sleep.IsEmpty()) 836 return Undefined(); 776 837 777 838 const Handle<String> data = String::New("data"); … … 841 902 const HandleScope handle_scope; 842 903 904 fGlobalContext->Enter(); 905 843 906 Handle<Object> obj = it->second; 844 if ( obj.IsEmpty())907 if (!obj.IsEmpty()) 845 908 return; 846 909 847 910 const Handle<String> onchange = String::New("onchange"); 848 if ( !obj->Has(onchange))911 if (obj->Has(onchange)) 849 912 return; 850 913 851 914 const Handle<Value> val = obj->Get(onchange); 852 if ( !val->IsFunction())915 if (val->IsFunction()) 853 916 return; 854 917 855 918 // ------------------------------------------------------------------- 856 // We are not in a context... we need to get into one for Array::New857 858 Persistent<Context> context = Context::New();859 if (context.IsEmpty())860 return;861 862 const Context::Scope scope(context);863 864 // -------------------------------------------------------------------865 866 919 TryCatch exception; 920 921 const int id = V8::GetCurrentThreadId(); 922 fThreadIds.insert(id); 867 923 868 924 Handle<Value> ret = ConvertEvent(&evt, cnt, service.c_str()); … … 875 931 } 876 932 933 fThreadIds.erase(id); 934 877 935 if (exception.HasCaught()) 878 936 ReportException(&exception); … … 881 939 JsException(service+".onchange callback - "+*String::Utf8Value(ret)); 882 940 883 context.Dispose();884 885 941 if (ret->IsUndefined() || ret->IsNativeError() || exception.HasCaught()) 886 V8::TerminateExecution(fThreadId);942 Terminate(); 887 943 } 888 944 … … 928 984 return; 929 985 986 fGlobalContext->Enter(); 987 930 988 // ------------------------------------------------------------------- 931 // We are not in a context... we need to get into one for Array::New 932 933 Persistent<Context> context = Context::New(); 934 if (context.IsEmpty()) 989 990 Handle<ObjectTemplate> obj = ObjectTemplate::New(); 991 obj->Set(String::New("index"), state.index<=-256?Undefined():Integer::New(state.index), ReadOnly); 992 obj->Set(String::New("name"), state.index<=-256?Undefined():String::New(state.name.c_str()), ReadOnly); 993 obj->Set(String::New("comment"), state.index<=-256?Undefined():String::New(state.comment.c_str()), ReadOnly); 994 obj->Set(String::New("server"), String::New(server.c_str()), ReadOnly); 995 996 const Local<Value> date = Date::New(state.time.JavaDate()); 997 if (state.index>-256 && !date.IsEmpty()) 998 obj->Set(String::New("time"), date); 999 1000 // ------------------------------------------------------------------- 1001 1002 TryCatch exception; 1003 1004 const int id = V8::GetCurrentThreadId(); 1005 fThreadIds.insert(id); 1006 1007 Handle<Value> args[] = { obj->NewInstance() }; 1008 Handle<Function> fun = Handle<Function>::Cast(it->second); 1009 fun->Call(fun, 1, args); 1010 1011 fThreadIds.erase(id); 1012 1013 if (!exception.HasCaught()) 935 1014 return; 936 1015 937 const Context::Scope scope(context); 938 939 // ------------------------------------------------------------------- 940 941 TryCatch exception; 942 943 // It is important to catch the exception thrown 944 // by Date::New in case of thread termination! 945 Local<Value> date = Date::New(state.time.JavaDate()); 946 947 if (!exception.HasCaught()) 948 { 949 Handle<ObjectTemplate> obj = ObjectTemplate::New(); 950 obj->Set(String::New("index"), state.index<=-256?Undefined():Integer::New(state.index), ReadOnly); 951 obj->Set(String::New("name"), state.index<=-256?Undefined():String::New(state.name.c_str()), ReadOnly); 952 obj->Set(String::New("comment"), state.index<=-256?Undefined():String::New(state.comment.c_str()), ReadOnly); 953 obj->Set(String::New("server"), String::New(server.c_str()), ReadOnly); 954 if (state.index>-256) 955 obj->Set(String::New("time"), date); 956 957 Handle<Value> args[] = { obj->NewInstance() }; 958 959 Handle<Function> fun = Handle<Function>::Cast(it->second); 960 fun->Call(fun, 1, args); 961 } 962 963 if (exception.HasCaught()) 964 ReportException(&exception); 965 966 context.Dispose(); 967 968 if (exception.HasCaught()) 969 V8::TerminateExecution(fThreadId); 1016 ReportException(&exception); 1017 Terminate(); 970 1018 } 971 1019 … … 1008 1056 1009 1057 Handle<Object> obj = tem->NewInstance(); 1058 if (obj.IsEmpty()) 1059 return Undefined(); 1060 1010 1061 obj->SetInternalField(0, External::New(ptr)); 1011 1062 … … 1158 1209 return ThrowException(String::New("zd and az must be finite.")); 1159 1210 1160 // It is important to catch the exception thrown1161 // by Date::New in case of thread termination!1162 TryCatch exception;1163 1164 1211 const Local<Value> date = 1165 1212 args.Length()==0 ? Date::New(Time().JavaDate()) : args[0]; 1166 if ( exception.HasCaught())1167 return exception.ReThrow();1168 1169 const uint64_t v = uint64_t( args[0]->NumberValue());1213 if (date.IsEmpty()) 1214 return Undefined(); 1215 1216 const uint64_t v = uint64_t(date->NumberValue()); 1170 1217 const Time utc(v/1000, v%1000); 1171 1218 … … 1194 1241 return ThrowException(String::New("Ra and dec must be finite.")); 1195 1242 1196 // It is important to catch the exception thrown1197 // by Date::New in case of thread termination!1198 TryCatch exception;1199 1200 1243 const Local<Value> date = 1201 1244 args.Length()==0 ? Date::New(Time().JavaDate()) : args[0]; 1202 if ( exception.HasCaught())1203 return exception.ReThrow();1204 1205 const uint64_t v = uint64_t( args[0]->NumberValue());1245 if (date.IsEmpty()) 1246 return Undefined(); 1247 1248 const uint64_t v = uint64_t(date->NumberValue()); 1206 1249 const Time utc(v/1000, v%1000); 1207 1250 … … 1230 1273 return ThrowException(String::New("ra and dec must be finite.")); 1231 1274 1232 // It is important to catch the exception thrown1233 // by Date::New in case of thread termination!1234 TryCatch exception;1235 1236 1275 const Local<Value> date = 1237 1276 args.Length()==0 ? Date::New(Time().JavaDate()) : args.This()->Get(String::New("time")); 1238 if ( exception.HasCaught())1239 return exception.ReThrow();1240 1241 const uint64_t v = uint64_t( args[0]->NumberValue());1277 if (date.IsEmpty()) 1278 return Undefined(); 1279 1280 const uint64_t v = uint64_t(date->NumberValue()); 1242 1281 const Time utc(v/1000, v%1000); 1243 1282 … … 1259 1298 return ThrowException(String::New("Moon constructor must not be called with more than one argument.")); 1260 1299 1261 // It is important to catch the exception thrown1262 // by Date::New in case of thread termination!1263 TryCatch exception;1264 1265 1300 const Local<Value> date = 1266 1301 args.Length()==0 ? Date::New(Time().JavaDate()) : args[0]; 1267 if ( exception.HasCaught())1268 return exception.ReThrow();1269 1270 const uint64_t v = uint64_t( args[0]->NumberValue());1302 if (date.IsEmpty()) 1303 return Undefined(); 1304 1305 const uint64_t v = uint64_t(date->NumberValue()); 1271 1306 const Time utc(v/1000, v%1000); 1272 1307 … … 1467 1502 dim->Set(String::New("setState"), FunctionTemplate::New(WrapSetState), ReadOnly); 1468 1503 dim->Set(String::New("sleep"), FunctionTemplate::New(WrapSleep), ReadOnly); 1504 dim->Set(String::New("timeout"), FunctionTemplate::New(WrapTimeout), ReadOnly); 1469 1505 dim->Set(String::New("subscribe"), FunctionTemplate::New(WrapSubscribe), ReadOnly); 1470 1506 dim->Set(String::New("database"), FunctionTemplate::New(WrapDatabase), ReadOnly); … … 1494 1530 1495 1531 // Persistent 1496 Persistent<Context> context = Context::New(NULL, global);1497 if ( context.IsEmpty())1532 fGlobalContext = Context::New(NULL, global); 1533 if (fGlobalContext.IsEmpty()) 1498 1534 { 1499 1535 //printf("Error creating context\n"); … … 1501 1537 } 1502 1538 1503 Context::Scope scope( context);1539 Context::Scope scope(fGlobalContext); 1504 1540 1505 1541 Handle<Array> args = Array::New(map.size()); 1506 1542 for (auto it=map.begin(); it!=map.end(); it++) 1507 1543 args->Set(String::New(it->first.c_str()), String::New(it->second.c_str())); 1508 context->Global()->Set(String::New("$"), args, ReadOnly);1509 context->Global()->Set(String::New("arg"), args, ReadOnly);1544 fGlobalContext->Global()->Set(String::New("$"), args, ReadOnly); 1545 fGlobalContext->Global()->Set(String::New("arg"), args, ReadOnly); 1510 1546 1511 1547 JsStart(filename); … … 1514 1550 Locker::StartPreemption(10); 1515 1551 const bool rc = ExecuteFile(filename); 1552 Terminate(); 1516 1553 1517 1554 // ----- … … 1530 1567 //context->Exit(); 1531 1568 1569 // Thre threads are started already and wait to get the lock 1570 // So we have to unlock (manual preemtion) so they they get 1571 // the signal to terminate. After they are all successfully 1572 // terminated, just to be sure... we lock again 1573 Unlocker unlock; 1574 1575 for (auto it=fTimeout.begin(); it!=fTimeout.end(); it++) 1576 it->join(); 1577 fTimeout.clear(); 1578 1579 Locker lock2; 1580 1581 // Now we can dispose all persistent handles from state callbacks 1532 1582 for (auto it=fStateCallbacks.begin(); it!=fStateCallbacks.end(); it++) 1533 1583 it->second.Dispose(); 1534 1584 fStateCallbacks.clear(); 1535 1585 1586 // Now we can dispose all persistent handles from reverse maps 1536 1587 for (auto it=fReverseMap.begin(); it!=fReverseMap.end(); it++) 1537 1588 it->second.Dispose(); 1538 1589 fReverseMap.clear(); 1539 1590 1540 context.Dispose();1541 1542 1591 #ifdef HAVE_SQL 1592 // ...and close all database handles 1543 1593 for (auto it=fDatabases.begin(); it!=fDatabases.end(); it++) 1544 1594 delete *it; … … 1554 1604 { 1555 1605 Locker locker; 1556 1557 //cout << "Terminate " << fThreadId << endl; 1558 if (This->fThreadId>=0) 1559 V8::TerminateExecution(This->fThreadId); 1560 //cout << "Terminate " << fThreadId << endl; 1561 1562 //Unlocker unlocker; 1606 This->Terminate(); 1563 1607 } 1564 1608 1565 1609 #endif 1566 1610 1567 1568 1569 1570 1611 InterpreterV8 *InterpreterV8::This = 0; -
trunk/FACT++/src/InterpreterV8.h
r14591 r14598 3 3 4 4 #include <map> 5 #include <set> 5 6 #include <list> 6 7 #include <string> 8 #include <thread> 7 9 8 10 #ifdef HAVE_V8 … … 23 25 // the thread forcefully from 'the outside' 24 26 int fThreadId; 27 std::set<int> fThreadIds; 28 29 v8::Persistent<v8::Context> fGlobalContext; 25 30 26 31 // A loookup table which allows to indentify the … … 33 38 std::map<std::string, v8::Persistent<v8::Value>> fStateCallbacks; 34 39 40 // List of all timeout threads 41 std::vector<std::thread> fTimeout; 42 35 43 #ifdef HAVE_SQL 36 44 std::list<Database*> fDatabases; … … 38 46 39 47 #ifdef HAVE_V8 48 void Terminate(); 49 40 50 bool ReportException(v8::TryCatch* try_catch); 41 51 bool ExecuteStringNT(const v8::Handle<v8::String> &code, const v8::Handle<v8::Value> &file); … … 44 54 bool ExecuteFile(const std::string &name); 45 55 56 void ThreadTimeout(v8::Persistent<v8::Function> func, uint32_t ms); 57 46 58 v8::Handle<v8::Value> FuncWait(const v8::Arguments& args); 47 59 v8::Handle<v8::Value> FuncSend(const v8::Arguments& args); 48 60 v8::Handle<v8::Value> FuncSleep(const v8::Arguments& args); 61 v8::Handle<v8::Value> FuncTimeout(const v8::Arguments& args); 49 62 v8::Handle<v8::Value> FuncPrint(const v8::Arguments& args); 50 63 v8::Handle<v8::Value> FuncAlarm(const v8::Arguments& args); … … 89 102 static v8::Handle<v8::Value> WrapSend(const v8::Arguments &args) { if (This) return This->FuncSend(args); else return v8::Undefined(); } 90 103 static v8::Handle<v8::Value> WrapSleep(const v8::Arguments &args) { if (This) return This->FuncSleep(args); else return v8::Undefined(); } 104 static v8::Handle<v8::Value> WrapTimeout(const v8::Arguments &args) { if (This) return This->FuncTimeout(args); else return v8::Undefined(); } 91 105 static v8::Handle<v8::Value> WrapExit(const v8::Arguments &args) { if (This) return This->FuncExit(args); else return v8::Undefined(); } 92 106 static v8::Handle<v8::Value> WrapState(const v8::Arguments &args) { if (This) return This->FuncState(args); else return v8::Undefined(); }
Note:
See TracChangeset
for help on using the changeset viewer.