17 #include <libguile/backtrace.h>
18 #include <libguile/debug.h>
20 #include <libguile/lang.h>
24 #include <opencog/util/Logger.h>
25 #include <opencog/util/oc_assert.h>
26 #include <opencog/util/platform.h>
33 using namespace opencog;
44 scm_c_eval_string (
"(setlocale LC_ALL "")\n");
66 _rc = scm_gc_protect_object(
_rc);
89 std::lock_guard<std::mutex> lck(
init_mtx);
100 SCM pair = scm_pipe();
101 _pipe = scm_car(pair);
106 scm_setvbuf(
_outport, scm_from_int (_IONBF), SCM_UNDEFINED);
109 int flags = fcntl(
_pipeno, F_GETFL, 0);
110 if (flags < 0) flags = 0;
111 fcntl(
_pipeno, F_SETFL, flags | O_NONBLOCK);
129 scm_set_current_output_port(
_outport);
159 scm_gc_unprotect_object(
_rc);
161 std::lock_guard<std::mutex> lck(
init_mtx);
169 scm_close_port(
_pipe);
170 scm_gc_unprotect_object(
_pipe);
194 scm_gc_unprotect_object(oldstack);
201 scm_gc_unprotect_object(olderror);
208 #define WORK_AROUND_GUILE_185_BUG
210 #ifdef WORK_AROUND_GUILE_185_BUG
224 scm_c_eval_string (
"(+ 2 2)\n");
230 #define WORK_AROUND_GUILE_THREADING_BUG
232 #ifdef WORK_AROUND_GUILE_THREADING_BUG
264 #ifdef WORK_AROUND_GUILE_THREADING_BUG
266 pthread_key_create(&
ser_key, NULL);
267 pthread_setspecific(
ser_key, (
const void *) 0x0);
269 #ifdef WORK_AROUND_GUILE_185_BUG
275 #ifdef WORK_AROUND_GUILE_THREADING_BUG
283 long cnt = (long) pthread_getspecific(
ser_key);
289 pthread_setspecific(
ser_key, (
const void *) cnt);
294 long cnt = (long) pthread_getspecific(
ser_key);
296 pthread_setspecific(
ser_key, (
const void *) cnt);
308 #ifdef WORK_AROUND_GUILE_THREADING_BUG
315 #ifdef WORK_AROUND_GUILE_THREADING_BUG
328 #ifdef WORK_AROUND_GUILE_185_BUG
333 scm_c_eval_string (
"(setlocale LC_ALL "")\n");
349 else if (scm_is_eq(node, SCM_UNSPECIFIED))
356 SCM port = scm_open_output_string();
357 scm_display (node, port);
358 SCM rc = scm_get_output_string(port);
359 char * str = scm_to_utf8_string(rc);
360 std::string rv = str;
362 scm_close_port(port);
395 SCM re = scm_symbol_to_string(tag);
396 char * restr = scm_to_utf8_string(re);
399 if (0 == strcmp(restr,
"read-error"))
408 if (0 == strcmp(restr,
"cog-yield"))
411 return SCM_CAR(throw_args);
419 SCM port = scm_open_output_string();
421 if (scm_is_true(scm_list_p(throw_args)) && (scm_ilength(throw_args) >= 1))
423 long nargs = scm_ilength(throw_args);
424 SCM subr = SCM_CAR (throw_args);
425 SCM message = SCM_EOL;
427 message = SCM_CADR (throw_args);
430 parts = SCM_CADDR (throw_args);
433 rest = SCM_CADDDR (throw_args);
439 if (scm_is_eq (tag, scm_arg_type_key) ||
440 scm_is_eq (tag, scm_out_of_range_key))
443 highlights = SCM_EOL;
445 scm_puts (
"Backtrace:\n", port);
447 SCM_BOOL_F, SCM_BOOL_F,
455 scm_display_error (
captured_stack, port, subr, message, parts, rest);
459 scm_puts (
"ERROR: throw args are unexpectedly short!\n", port);
461 scm_puts(
"ABORT: ", port);
462 scm_puts(restr, port);
466 scm_close_port(port);
500 #ifdef WORK_AROUND_GUILE_THREADING_BUG
511 #ifdef WORK_AROUND_GUILE_THREADING_BUG
519 self->
answer =
self->do_poll_result();
536 OC_ASSERT(
self,
"c_wrap_eval got null pointer!");
537 OC_ASSERT(self->pexpr,
"c_wrap_eval got null expression!");
539 self->do_eval(*(self->pexpr));
553 static size_t prev_usage = 0;
555 size_t curr_usage = getMemUsage();
557 if (10 * 1024 * 1024 < curr_usage - prev_usage)
559 prev_usage = curr_usage;
564 static SCM since = scm_from_utf8_symbol(
"heap-allocated-since-gc");
565 SCM stats = scm_gc_stats();
566 size_t allo = scm_to_size_t(scm_assoc_ref(stats, since));
568 int times = scm_to_int(scm_assoc_ref(stats, scm_from_utf8_symbol(
"gc-times")));
569 printf(
"allo=%lu mem=%lu time=%d\n", allo/1024, (getMemUsage() / (1024)), times);
571 logger().info() <<
"Guile evaluated: " << expr;
572 logger().info() <<
"Mem usage=" << (getMemUsage() / (1024*1024)) <<
"MB";
605 scm_gc_unprotect_object(
_rc);
606 SCM eval_str = scm_from_utf8_string(
_input_line.c_str());
607 _rc = scm_c_catch (SCM_BOOL_T,
608 (scm_t_catch_body) scm_eval_string,
612 _rc = scm_gc_protect_object(_rc);
650 if (-1 == nr)
return rv;
692 std::unique_lock<std::mutex> lck(
_poll_mtx);
693 while (not _eval_done)
695 _wait_done.wait_for(lck, std::chrono::milliseconds(300));
697 if (0 < rv.size())
return rv;
708 scm_gc_unprotect_object(
_rc);
710 _rc = scm_gc_protect_object(
_rc);
744 scm_remember_upto_here_1(tmp_rc);
747 return "#<Error: Unreachable statement reached>";
786 SCM rc = scm_c_catch (SCM_BOOL_T,
828 logger().info(
"%s: Output: %s\n"
829 "Was generated by expr: %s\n",
830 __FUNCTION__, str.c_str(),
prt(sexpr).c_str());
850 return scm_eval_string((SCM)expr);
865 SCM expr_str = scm_from_utf8_string(expr.c_str());
870 #ifdef WORK_AROUND_GUILE_THREADING_BUG
879 #ifdef WORK_AROUND_GUILE_THREADING_BUG
885 throw RuntimeException(TRACE_INFO,
error_msg.c_str());
894 SCM expr_str = scm_from_utf8_string(self->pexpr->c_str());
912 SCM expr_str = scm_from_utf8_string(expr.c_str());
920 #ifdef WORK_AROUND_GUILE_THREADING_BUG
929 #ifdef WORK_AROUND_GUILE_THREADING_BUG
935 throw RuntimeException(TRACE_INFO,
error_msg.c_str());
944 SCM expr_str = scm_from_utf8_string(self->pexpr->c_str());
948 if (self->eval_error())
return self;
972 #ifdef WORK_AROUND_GUILE_THREADING_BUG
982 #ifdef WORK_AROUND_GUILE_THREADING_BUG
986 throw RuntimeException(TRACE_INFO,
error_msg.c_str());
994 self->
hargs =
self->do_apply(*self->pexpr, self->hargs);
1016 return scm_eval((SCM)expr, scm_interaction_environment());
1027 SCM sfunc = scm_from_utf8_symbol(func.c_str());
1034 size_t sz = oset.size();
1035 for (
int i=sz-1; i>=0; i--)
1038 expr = scm_cons(sh, expr);
1040 expr = scm_cons(sfunc, expr);
1065 #ifdef WORK_AROUND_GUILE_THREADING_BUG
1075 #ifdef WORK_AROUND_GUILE_THREADING_BUG
1079 throw RuntimeException(TRACE_INFO,
error_msg.c_str());
1091 SCM tv_smob =
self->
do_apply_scm(*self->pexpr, self->hargs);
1092 if (self->eval_error())
return self;
1105 static concurrent_stack<SchemeEval*>
pool;
1110 std::lock_guard<std::mutex> lock(
pool_mtx);
1112 if (
pool.try_pop(ev))
return ev;
1118 std::lock_guard<std::mutex> lock(
pool_mtx);
1137 static thread_local std::map<AtomSpace*,SchemeEval*> issued;
1143 for (
auto ev : issued)
1159 static thread_local eval_dtor killer;
1161 auto ev = issued.find(as);
1162 if (ev != issued.end())
1167 issued[as] = evaluator;
1171 if (evaluator->recursing())
1172 throw RuntimeException(TRACE_INFO,
1173 "Evaluator thread singleton used recursively!");
void eval_expr(const std::string &)
static void * c_wrap_apply_tv(void *)
static pthread_key_t ser_key
static pthread_mutex_t serialize_lock
static concurrent_stack< SchemeEval * > pool
Handle apply(const std::string &func, Handle varargs)
static std::mutex pool_mtx
SCM recast_scm_eval_string(void *expr)
std::condition_variable _wait_done
void drain_output()
Discard all chars in the outport.
std::shared_ptr< TruthValue > TruthValuePtr
static SCM thunk_scm_eval(void *expr)
static scm_t_bits cog_misc_tag
static void init_scheme(void)
static void * c_wrap_eval_tv(void *)
std::string poll_result()
static SCM guile_user_module
static void * c_wrap_poll(void *)
const std::string * pexpr
virtual bool eval_error(void)
SCM do_apply_scm(const std::string &func, Handle &varargs)
static void ss_set_env_as(AtomSpace *)
static SchemeEval * get_evaluator(AtomSpace *=NULL)
Handle eval_h(const std::string &)
static void * c_wrap_eval(void *)
static TruthValuePtr NULL_TV()
SCM preunwind_handler(SCM, SCM)
std::string do_poll_result()
static Handle scm_to_handle(SCM)
SCM catch_handler(SCM, SCM)
SchemeEval(AtomSpace *=NULL)
void set_captured_stack(SCM)
static void * c_wrap_finish(void *)
static SCM preunwind_handler_wrapper(void *, SCM, SCM)
static void return_to_pool(SchemeEval *ev)
void per_thread_init(void)
static void * c_wrap_set_atomspace(void *)
TruthValuePtr apply_tv(const std::string &func, Handle varargs)
static void * c_wrap_apply(void *)
static std::atomic_flag eval_is_inited
static void set_scheme_as(AtomSpace *)
static void * c_wrap_eval_h(void *)
void set_error_string(SCM)
static SCM handle_to_scm(Handle)
static thread_local bool thread_is_inited
static SchemeEval * get_from_pool(void)
static TruthValuePtr to_tv(SCM)
void do_eval(const std::string &)
static AtomSpace * ss_get_env_as(const char *)
SCM do_scm_eval(SCM, SCM(*)(void *))
static SCM catch_handler_wrapper(void *, SCM, SCM)
static std::string prt(SCM)
static std::string misc_to_string(SCM)
static void * c_wrap_init(void *)
static void init_only_once(void)
const HandleSeq & get_outgoing(Handle h) const
TruthValuePtr eval_tv(const std::string &)
static void * do_bogus_scm(void *p)
Handle do_apply(const std::string &func, Handle &varargs)