Another rework for scripthooks, for better performance.
All checks were successful
continuous-integration/drone/push Build is passing

This new version caches pointers to the pointers to scripts, so that we can build the data once and then simply iterate over it whenever we want to run a hook.
This commit is contained in:
2019-11-10 17:08:42 +01:00
parent e1a8d80863
commit d8332f9e40
19 changed files with 118 additions and 72 deletions

View File

@@ -6,26 +6,23 @@
#include "Script.hpp"
#include "ScriptSet.hpp"
#include "../../Core/Exceptions/NotReachableException.hpp"
#include "ScriptWrapper.hpp"
namespace CreatureLib::Battling{
class ScriptAggregator{
std::queue<std::any> _queue;
__gnu_cxx::__normal_iterator<ScriptWrapper *, std::vector<ScriptWrapper>> _selfIterator;
__gnu_cxx::__normal_iterator<ScriptWrapper *, std::vector<ScriptWrapper>> _selfEnd;
bool _isSetSet = false;
std::__detail::_Node_const_iterator<std::pair<const std::string, Script *>, false, true> _setIterator;
std::__detail::_Node_const_iterator<std::pair<const std::string, Script *>, false, true> _setEnd;
public:
ScriptAggregator() = default;
void Add(Script* script){
_queue.push(script);
}
void Add(const ScriptSet* scriptSet){
_queue.push(scriptSet);
}
ScriptAggregator(std::vector<ScriptWrapper> scripts){
_selfIterator = scripts.begin();
_selfEnd = scripts.end();
};
bool HasNext(){
return !_queue.empty() || _isSetSet;
return _selfIterator != _selfEnd || _isSetSet;
}
Script* GetNext(){
@@ -42,15 +39,17 @@ namespace CreatureLib::Battling{
}
return s;
}
if (_queue.empty())
if (_selfIterator == _selfEnd)
return nullptr;
auto next = _queue.front();
_queue.pop();
if (next.type() == typeid(Script*)){
return std::any_cast<Script*>(next);
auto next = *_selfIterator;
if (!next.IsSet()){
auto scriptPtr = next.GetScript();
if (scriptPtr == nullptr)
return GetNext();
return *scriptPtr;
}
else{
auto set = std::any_cast<const ScriptSet*>(next);
auto set = next.GetScriptSet();
if (set->Count() == 0)
return GetNext();
auto it = set->GetIterator();

View File

@@ -1,7 +1,6 @@
#define HOOK(hookName, source, ... ) \
{ \
auto aggregator = CreatureLib::Battling::ScriptAggregator(); \
source -> GetActiveScripts(aggregator); \
auto aggregator = source -> GetScriptIterator(); \
while (aggregator.HasNext()){ \
auto next = aggregator.GetNext(); \
if (next == nullptr) continue; \

View File

@@ -7,8 +7,18 @@
namespace CreatureLib::Battling{
class ScriptSource {
bool _areScriptsInitialized = false;
std::vector<ScriptWrapper> _scripts;
protected:
virtual void GetActiveScripts(std::vector<ScriptWrapper>& scripts) = 0;
public:
virtual void GetActiveScripts(ScriptAggregator& aggr) const = 0;
ScriptAggregator GetScriptIterator(){
if (!_areScriptsInitialized){
GetActiveScripts(_scripts);
_areScriptsInitialized = true;
}
return ScriptAggregator(_scripts);
}
};
}

View File

@@ -0,0 +1,3 @@
#include "ScriptWrapper.hpp"

View File

@@ -0,0 +1,33 @@
#ifndef CREATURELIB_SCRIPTWRAPPER_HPP
#define CREATURELIB_SCRIPTWRAPPER_HPP
#include <variant>
#include "Script.hpp"
#include "ScriptSet.hpp"
namespace CreatureLib::Battling{
class ScriptWrapper {
std::variant<Script**, ScriptSet*> _value;
bool _isSet;
public:
ScriptWrapper(Script** s) : _value(s), _isSet(false){}
ScriptWrapper(ScriptSet* s) : _value(s), _isSet(true){}
bool IsSet() const{
return _isSet;
}
Script** GetScript() const{
return std::get<Script**>(_value);
}
ScriptSet* GetScriptSet() const{
return std::get<ScriptSet*>(_value);
}
};
}
#endif //CREATURELIB_SCRIPTWRAPPER_HPP