diff options
author | 2011-05-18 10:24:09 +0300 | |
---|---|---|
committer | 2011-05-18 15:43:01 +0300 | |
commit | 1db4915f98c4a6943aa685840a2353c029ec3309 (patch) | |
tree | 61d378ee06b8ab9171d6bb1ac983114f41f2a69d /src | |
parent | Builtins: support null command (diff) | |
download | libbash-1db4915f98c4a6943aa685840a2353c029ec3309.tar.gz libbash-1db4915f98c4a6943aa685840a2353c029ec3309.tar.bz2 libbash-1db4915f98c4a6943aa685840a2353c029ec3309.zip |
multithread
Diffstat (limited to 'src')
-rw-r--r-- | src/builtins/source_builtin.cpp | 43 | ||||
-rw-r--r-- | src/core/bash_ast.cpp | 35 | ||||
-rw-r--r-- | src/core/bash_ast.h | 1 |
3 files changed, 59 insertions, 20 deletions
diff --git a/src/builtins/source_builtin.cpp b/src/builtins/source_builtin.cpp index 383b716..ee95e29 100644 --- a/src/builtins/source_builtin.cpp +++ b/src/builtins/source_builtin.cpp @@ -28,6 +28,7 @@ #include <iostream> #include <string> #include <unordered_map> +#include <thread> #include "builtins/builtin_exceptions.h" #include "cppbash_builtin.h" @@ -35,6 +36,31 @@ #include "core/interpreter_exception.h" #include "core/bash_ast.h" +namespace { + std::mutex parse_mutex; + + std::shared_ptr<bash_ast>& parse(const std::string& path) + { + static std::unordered_map<std::string, std::shared_ptr<bash_ast>> ast_cache; + + std::lock_guard<std::mutex> parse_lock(parse_mutex); + + auto& stored_ast = ast_cache[path]; + if(!stored_ast) + { + std::ifstream input(path); + if(!input) + throw interpreter_exception(path + " can't be read"); + + stored_ast.reset(new bash_ast(input)); + if(stored_ast->get_error_count()) + std::cerr << path << " could not be parsed properly" << std::endl; + } + + return stored_ast; + } +} + int source_builtin::exec(const std::vector<std::string>& bash_args) { static std::unordered_map<std::string, std::shared_ptr<bash_ast>> ast_cache; @@ -42,24 +68,9 @@ int source_builtin::exec(const std::vector<std::string>& bash_args) if(bash_args.size() == 0) throw interpreter_exception("should provide one argument for source builtin"); - // we need fix this to pass extra arguments as positional parameters - const std::string& path = bash_args[0]; - - auto& stored_ast = ast_cache[path]; - if(!stored_ast) - { - std::ifstream input(path); - if(!input) - throw interpreter_exception(path + " can't be read"); - - stored_ast.reset(new bash_ast(input)); - if(stored_ast->get_error_count()) - std::cerr << path << " could not be parsed properly" << std::endl; - } - try { - stored_ast->interpret_with(_walker); + parse(bash_args.front())->interpret_with(_walker); } catch(return_exception& e) {} diff --git a/src/core/bash_ast.cpp b/src/core/bash_ast.cpp index 0bf8938..2f729a4 100644 --- a/src/core/bash_ast.cpp +++ b/src/core/bash_ast.cpp @@ -25,6 +25,7 @@ #include "core/bash_ast.h" #include <sstream> +#include <thread> #include "core/interpreter_exception.h" #include "core/interpreter.h" @@ -49,9 +50,30 @@ bash_ast::bash_ast(std::istream& source): error_count(0) init_parser(); } +namespace +{ + std::mutex string_mutex; + + pANTLR3_STRING locked_newRaw8(pANTLR3_STRING_FACTORY factory) + { + std::lock_guard<std::mutex> l(string_mutex); + pANTLR3_STRING_FACTORY pristine = antlr3StringFactoryNew(); + pANTLR3_STRING result = pristine->newRaw(factory); + pristine->close(pristine); + return result; + } + + void locked_destroy(pANTLR3_STRING_FACTORY factory, pANTLR3_STRING string) + { + std::lock_guard<std::mutex> l(string_mutex); + pANTLR3_STRING_FACTORY pristine = antlr3StringFactoryNew(); + pristine->destroy(factory, string); + pristine->close(pristine); + } +} + bash_ast::~bash_ast() { - nodes->free(nodes); psr->free(psr); tstream->free(tstream); lxr->free(lxr); @@ -86,22 +108,29 @@ void bash_ast::init_parser() } langAST.reset(new libbashParser_start_return(psr->start(psr))); + langAST->tree->strFactory->newRaw = &locked_newRaw8; + langAST->tree->strFactory->destroy = &locked_destroy; error_count = psr->pParser->rec->getNumberOfSyntaxErrors(psr->pParser->rec); - nodes = antlr3CommonTreeNodeStreamNewTree(langAST->tree, ANTLR3_SIZE_HINT); } void bash_ast::interpret_with(interpreter& walker) { set_interpreter(&walker); + + auto nodes = antlr3CommonTreeNodeStreamNewTree(langAST->tree, ANTLR3_SIZE_HINT); plibbashWalker treePsr = libbashWalkerNew(nodes); treePsr->start(treePsr); treePsr->free(treePsr); + nodes->free(nodes); } std::string bash_ast::get_dot_graph() { + auto nodes = antlr3CommonTreeNodeStreamNewTree(langAST->tree, ANTLR3_SIZE_HINT); pANTLR3_STRING graph = nodes->adaptor->makeDot(nodes->adaptor, langAST->tree); - return std::string(reinterpret_cast<char*>(graph->chars)); + std::string result(reinterpret_cast<char*>(graph->chars)); + nodes->free(nodes); + return result; } std::string bash_ast::get_string_tree() diff --git a/src/core/bash_ast.h b/src/core/bash_ast.h index e587d81..852899c 100644 --- a/src/core/bash_ast.h +++ b/src/core/bash_ast.h @@ -47,7 +47,6 @@ class bash_ast pANTLR3_COMMON_TOKEN_STREAM tstream; libbashParser_Ctx_struct* psr; std::unique_ptr<libbashParser_start_return_struct> langAST; - pANTLR3_COMMON_TREE_NODE_STREAM nodes; int error_count; void init_parser(); |