better (thread) error handling
This commit is contained in:
parent
c17d43724a
commit
af92d1f870
24
ml.cpp
24
ml.cpp
|
|
@ -22,6 +22,7 @@
|
||||||
#include <ctime>
|
#include <ctime>
|
||||||
#include <chrono>
|
#include <chrono>
|
||||||
#include <thread>
|
#include <thread>
|
||||||
|
#include <mutex>
|
||||||
|
|
||||||
|
|
||||||
#define TOO_FEW_ARGS "too few arguments to function"
|
#define TOO_FEW_ARGS "too few arguments to function"
|
||||||
|
|
@ -624,12 +625,16 @@ MlError::~MlError() {
|
||||||
delete cause;
|
delete cause;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string MlError::description() {
|
std::string MlError::description() const {
|
||||||
// return "error: the expression `" + cause->debug() + "` failed in scope " + to_string(env) + " with message \"" + msg + "\"";
|
// return "error: the expression `" + cause->debug() + "` failed in scope " + to_string(env) + " with message \"" + msg + "\"";
|
||||||
return MlPerfMon::instance().callstack() +
|
return MlPerfMon::instance().callstack() +
|
||||||
"error: the expression `" + cause->debug() + "` with message \"" + msg + "\"";
|
"error: the expression `" + cause->debug() + "` with message \"" + msg + "\"";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const char* MlError::what() const noexcept {
|
||||||
|
return ("error: the expression `" + cause->debug() + "` with message \"" + msg + "\"").c_str();
|
||||||
|
}
|
||||||
|
|
||||||
void MlEnvironment::combine(MlEnvironment const &other) {
|
void MlEnvironment::combine(MlEnvironment const &other) {
|
||||||
// Normally, I would use the `insert` method of the `map` class,
|
// Normally, I would use the `insert` method of the `map` class,
|
||||||
// but it doesn't overwrite previously declared values for keys.
|
// but it doesn't overwrite previously declared values for keys.
|
||||||
|
|
@ -1753,8 +1758,12 @@ namespace builtin {
|
||||||
|
|
||||||
MlValue thread_create(std::vector<MlValue> args, MlEnvironment &env) {
|
MlValue thread_create(std::vector<MlValue> args, MlEnvironment &env) {
|
||||||
auto functor = [](std::vector<MlValue> args, MlEnvironment &env) -> void {
|
auto functor = [](std::vector<MlValue> args, MlEnvironment &env) -> void {
|
||||||
for (size_t i = 0; i < args.size(); i++)
|
try {
|
||||||
MlValue acc = args[i].eval(env);
|
for (size_t i = 0; i < args.size(); i++)
|
||||||
|
MlValue acc = args[i].eval(env);
|
||||||
|
} catch (std::exception &e) {
|
||||||
|
std::cerr << "thread exception: " << e.what() << std::endl;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
std::thread th(functor, args, std::ref(env));
|
std::thread th(functor, args, std::ref(env));
|
||||||
|
|
@ -1777,9 +1786,7 @@ namespace builtin {
|
||||||
if (args[0].as_string() != "ilock")
|
if (args[0].as_string() != "ilock")
|
||||||
throw MlError(MlValue("thread_under_lock", thread_under_lock), env, UNKNOWN_ERROR);
|
throw MlError(MlValue("thread_under_lock", thread_under_lock), env, UNKNOWN_ERROR);
|
||||||
|
|
||||||
|
|
||||||
std::lock_guard<std::mutex> lockGuard(interpreter_mutex);
|
std::lock_guard<std::mutex> lockGuard(interpreter_mutex);
|
||||||
|
|
||||||
MlValue acc;
|
MlValue acc;
|
||||||
for (size_t i = 0; i < args.size(); i++)
|
for (size_t i = 0; i < args.size(); i++)
|
||||||
acc = args[i].eval(env);
|
acc = args[i].eval(env);
|
||||||
|
|
@ -1791,6 +1798,7 @@ namespace builtin {
|
||||||
if (args.size() != 0)
|
if (args.size() != 0)
|
||||||
throw MlError(MlValue("threads_join", threads_join), env, TOO_MANY_ARGS);
|
throw MlError(MlValue("threads_join", threads_join), env, TOO_MANY_ARGS);
|
||||||
|
|
||||||
|
std::lock_guard<std::mutex> lockGuard(register_mutex);
|
||||||
for (auto &th : threads_register)
|
for (auto &th : threads_register)
|
||||||
if (th.joinable()) th.join();
|
if (th.joinable()) th.join();
|
||||||
|
|
||||||
|
|
@ -1841,7 +1849,7 @@ void repl(MlEnvironment &env) {
|
||||||
} catch (MlError &e) {
|
} catch (MlError &e) {
|
||||||
std::cerr << e.description() << std::endl;
|
std::cerr << e.description() << std::endl;
|
||||||
MlPerfMon::instance().clear_callstack();
|
MlPerfMon::instance().clear_callstack();
|
||||||
} catch (std::runtime_error &e) {
|
} catch (std::exception &e) {
|
||||||
std::cerr << e.what() << std::endl;
|
std::cerr << e.what() << std::endl;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -2065,8 +2073,8 @@ int main(int argc, char *argv[]) {
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
} catch (MlError &e) {
|
} catch (MlError &e) {
|
||||||
std::cerr << e.description() << std::endl;
|
std::cerr << e.what() << std::endl;
|
||||||
} catch (std::runtime_error &e) {
|
} catch (const std::exception &e) {
|
||||||
std::cerr << MlPerfMon::instance().callstack() << e.what() << std::endl;
|
std::cerr << MlPerfMon::instance().callstack() << e.what() << std::endl;
|
||||||
MlPerfMon::instance().clear_callstack();
|
MlPerfMon::instance().clear_callstack();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
9
ml.h
9
ml.h
|
|
@ -67,8 +67,10 @@ private:
|
||||||
|
|
||||||
|
|
||||||
// An exception thrown by the lisp
|
// An exception thrown by the lisp
|
||||||
class MlError {
|
class MlError : public std::exception {
|
||||||
public:
|
public:
|
||||||
|
MlError() = delete;
|
||||||
|
|
||||||
// Create an error with the value that caused the error,
|
// Create an error with the value that caused the error,
|
||||||
// the scope where the error was found, and the message.
|
// the scope where the error was found, and the message.
|
||||||
MlError(const MlValue &v, MlEnvironment const &env, const char *msg);
|
MlError(const MlValue &v, MlEnvironment const &env, const char *msg);
|
||||||
|
|
@ -79,7 +81,10 @@ public:
|
||||||
~MlError();
|
~MlError();
|
||||||
|
|
||||||
// Get the printable error description.
|
// Get the printable error description.
|
||||||
std::string description();
|
std::string description() const;
|
||||||
|
|
||||||
|
// inherited from std::exception
|
||||||
|
virtual const char* what() const noexcept;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
MlValue *cause;
|
MlValue *cause;
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue