Skip to content

Commit

Permalink
ApplicationMethods: have a application.executeMultiple, arrr
Browse files Browse the repository at this point in the history
  • Loading branch information
andreasdr committed Jan 6, 2025
1 parent 6ea0e65 commit 1d5e62a
Show file tree
Hide file tree
Showing 4 changed files with 146 additions and 14 deletions.
1 change: 0 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,6 @@ Also note the focus on easy integration into other products and easy customizabi
- [Operators](./documentation/README-Operators.md)
- [Constants](./documentation/README-Constants.md)


# 3. Links

- MinitScript, see [README.md](./README.md)
Expand Down
16 changes: 6 additions & 10 deletions documentation/README-BuiltIn-Functions.md
Original file line number Diff line number Diff line change
Expand Up @@ -115,8 +115,10 @@
|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| Get application command line arguments |
| <sub>application.getArguments(): Array</sub> |
| Execute Application |
| Execute application |
| <sub>application.execute($command: String[, &$exitCode: ?Integer[, &$error: ?String]]): String</sub>|
| Execute multiple applications |
| <sub>application.executeMultiple($commands: Array[, $concurrency: Integer]): Boolean</sub> |
| Exit application with optional exit code |
| <sub>application.exit([$exitCode: Integer]): Null</sub> |

Expand Down Expand Up @@ -334,24 +336,18 @@

| &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Table of methods &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; |
|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| Get named conditions |
| <sub>script.getNamedConditions(): String</sub> |
| Get global scope script variables |
| <sub>script.getGlobalVariables(): Map</sub> |
| Returns if script runs natively |
| <sub>script.isNative(): Boolean</sub> |
| Get script variables |
| Get current scope script variables |
| <sub>script.getVariables(): Map</sub> |
| Call script function |
| <sub>script.call($function: String, ...): Mixed</sub> |
| Call function by function variable |
| <sub>script.callFunction($function: Function, ...): Mixed</sub> |
| Call script stacklet |
| <sub>script.callStacklet($stacklet: String): Mixed</sub> |
| Disable a specific named condition |
| <sub>script.disableNamedCondition($name: String): Null</sub> |
| Emit a condition |
| <sub>script.emit($condition: String): Null</sub> |
| Enable a specific named condition |
| <sub>script.enableNamedCondition($name: String): Null</sub> |
| Evaluate a script statement |
| <sub>script.evaluate($statement: String): Mixed</sub> |
| Stop script |
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,8 @@ minitscript.basemethod.setVariable=Set variable
minitscript.basemethod.add=Add
minitscript.basemethod.and=Logical and
minitscript.basemethod.application.getArguments=Get application command line arguments
minitscript.basemethod.application.execute=Execute Application
minitscript.basemethod.application.execute=Execute application
minitscript.basemethod.application.executeMultiple=Execute multiple applications
minitscript.basemethod.application.exit=Exit application with optional exit code
minitscript.basemethod.Array=Create array
minitscript.basemethod.Array::get=Get array entry
Expand Down Expand Up @@ -230,7 +231,8 @@ minitscript.basemethod.prefixIncrement=Prefix increment
minitscript.basemethod.return=Returns from function with optional return value
minitscript.basemethod.script.getNamedConditions=Get named conditions
minitscript.basemethod.script.isNative=Returns if script runs natively
minitscript.basemethod.script.getVariables=Get script variables
minitscript.basemethod.script.getVariables=Get current scope script variables
minitscript.basemethod.script.getGlobalVariables=Get global scope script variables
minitscript.basemethod.script.call=Call script function
minitscript.basemethod.script.callFunction=Call function by function variable
minitscript.basemethod.script.callStacklet=Call script stacklet
Expand Down
137 changes: 136 additions & 1 deletion src/minitscript/minitscript/ApplicationMethods.cpp
Original file line number Diff line number Diff line change
@@ -1,25 +1,33 @@
#include <array>
#include <cstdio>
#include <cstdlib>
#include <span>
#include <memory>
#include <span>
#include <vector>

#include <minitscript/minitscript.h>
#include <minitscript/minitscript/ApplicationMethods.h>
#include <minitscript/minitscript/MinitScript.h>
#include <minitscript/os/filesystem/FileSystem.h>
#include <minitscript/os/threading/Mutex.h>
#include <minitscript/os/threading/Thread.h>
#include <minitscript/utilities/Console.h>
#include <minitscript/utilities/Exception.h>
#include <minitscript/utilities/StringTools.h>

using std::array;
using std::make_unique;
using std::span;
using std::shared_ptr;
using std::unique_ptr;
using std::vector;

using minitscript::minitscript::ApplicationMethods;

using minitscript::minitscript::MinitScript;
using minitscript::os::filesystem::FileSystem;
using minitscript::os::threading::Mutex;
using minitscript::os::threading::Thread;
using minitscript::utilities::Exception;

using _Console = minitscript::utilities::Console;
Expand Down Expand Up @@ -167,6 +175,133 @@ void ApplicationMethods::registerMethods(MinitScript* minitScript) {
};
minitScript->registerMethod(new MethodApplicationExecute(minitScript));
}
{
//
class MethodApplicationExecuteMultiple: public MinitScript::Method {
private:
MinitScript* minitScript { nullptr };
public:
MethodApplicationExecuteMultiple(MinitScript* minitScript):
MinitScript::Method(
{
{ .type = MinitScript::TYPE_ARRAY, .name = "commands", .optional = false, .reference = false, .nullable = false },
{ .type = MinitScript::TYPE_INTEGER, .name = "concurrency", .optional = true, .reference = false, .nullable = false }
},
MinitScript::TYPE_BOOLEAN
),
minitScript(minitScript) {}
const string getMethodName() override {
return "application.executeMultiple";
}
void executeMethod(span<MinitScript::Variable>& arguments, MinitScript::Variable& returnValue, const MinitScript::SubStatement& subStatement) override {
string command;
int64_t concurrency = 1;
if ((arguments.size() == 1 || arguments.size() == 2) &&
arguments[0].getType() == MinitScript::TYPE_ARRAY &&
MinitScript::getIntegerValue(arguments, 1, concurrency, true) == true) {
// collect commands
vector<string> commands;
auto arrayPtr = arguments[0].getArrayPointer();
if (arrayPtr != nullptr) {
for (auto arrayEntry: *arrayPtr) commands.push_back(arrayEntry->getValueAsString());
}
/**
* Execution commands container
*/
class ExecutionCommands {
private:
Mutex mutex;
const vector<string>& commands;
int commandIdx { 0 };
public:
/**
* Constructor
* @param commands commands
*/
ExecutionCommands(const vector<string>& commands): mutex("cmdlist-mutex"), commands(commands) {
}
/**
* @return returns left command
*/
bool getCommand(string& command) {
mutex.lock();
if (commandIdx >= commands.size()) {
mutex.unlock();
return false;
}
command = commands[commandIdx++];
mutex.unlock();
return true;
}
/**
* Stop delivering commands
*/
void stop() {
mutex.lock();
commandIdx = commands.size();
mutex.unlock();
}
};
/**
* Execution thread
*/
class ExecutionThread: public Thread {
private:
ExecutionCommands* executionCommands;
bool failure { false };
public:
/**
* Constructor
* @param commands commands
*/
ExecutionThread(ExecutionCommands* executionCommands): Thread("execution-thread"), executionCommands(executionCommands) {
}
/**
* @returns returns if an error has occurred
*/
inline bool hadFailure() {
return failure;
}
/**
* Run
*/
void run() {
string command;
while (executionCommands->getCommand(command) == true) {
int exitCode;
string error;
_Console::printLine(command);
auto result = ApplicationMethods::execute(command, &exitCode, &error);
if (result.empty() == false)_Console::printLine(result);
if (exitCode != EXIT_SUCCESS) {
executionCommands->stop();
if (error.empty() == false)_Console::printLine(error);
failure = true;
}
}
}
};
// execute
ExecutionCommands executionCommands(commands);
vector<unique_ptr<ExecutionThread>> executionThreads;
executionThreads.resize(concurrency);
for (auto i = 0; i < concurrency; i++) executionThreads[i] = make_unique<ExecutionThread>(&executionCommands);
for (auto i = 0; i < concurrency; i++) executionThreads[i]->start();
for (auto i = 0; i < concurrency; i++) executionThreads[i]->join();
// failure
auto success = true;
for (auto i = 0; i < concurrency; i++) {
if (executionThreads[i]->hadFailure() == true) success = false;
}
returnValue.setValue(success);
//
} else {
MINITSCRIPT_METHODUSAGE_COMPLAIN(getMethodName());
}
}
};
minitScript->registerMethod(new MethodApplicationExecuteMultiple(minitScript));
}
//
if (minitScript->getContext() != nullptr) {
//
Expand Down

0 comments on commit 1d5e62a

Please sign in to comment.