-
Notifications
You must be signed in to change notification settings - Fork 149
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Remote-Promise system #1414
base: master
Are you sure you want to change the base?
Remote-Promise system #1414
Changes from all commits
af5b472
fbd6d48
1bc3176
fed80b4
4a2d77f
49f3c9e
3a950e7
7024e75
a2cea8a
ac912c9
a673d2b
6164de7
e2068d1
5129a5d
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
x\cba\addons\promise |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
class CfgFunctions { | ||
class CBA { | ||
class Network { | ||
PATHTO_FNC(promise_create); | ||
PATHTO_FNC(promise_callback); | ||
PATHTO_FNC(promise_done); | ||
PATHTO_FNC(promise_receiver); | ||
PATHTO_FNC(promise_init); | ||
}; | ||
}; | ||
}; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
#include "script_component.hpp" | ||
|
||
class CfgPatches { | ||
class ADDON { | ||
author = "$STR_CBA_Author"; | ||
name = CSTRING(component); | ||
url = "$STR_CBA_URL"; | ||
units[] = {}; | ||
weapons[] = {}; | ||
requiredVersion = REQUIRED_VERSION; | ||
requiredAddons[] = {}; | ||
version = VERSION; | ||
authors[] = {"X39"}; | ||
}; | ||
}; | ||
|
||
#include "CfgFunctions.hpp" |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
/* ---------------------------------------------------------------------------- | ||
Function: CBA_fnc_promise_callback | ||
|
||
Description: | ||
Function that gets called when the receiver is done. | ||
Will in the end execute the promise-code locally. | ||
|
||
WARNING! Not intended to be called by client-code! | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Pretty sure we have a Public: No doc token for this very purpose. It's also another argument to define these functions using PREP() instead of CfgFunctions, because generally only API is exposed to CfgFunctions. See the settings-component, where the CfgFunctions functions are just wrappers for the internal PREP()ed functions with some preInit handling. |
||
|
||
Parameters: | ||
_id - The Promise-ID of the now finished promise. <ARRAY> | ||
_data - The result data of the now finished promise. <ANY> | ||
|
||
Returns: | ||
Nothing | ||
|
||
Example: | ||
Nothing | ||
|
||
Author: | ||
X39 | ||
---------------------------------------------------------------------------- */ | ||
#include "script_component.hpp" | ||
|
||
params ["_id", "_data"]; | ||
private _request = GVAR(requests) select _id; | ||
GVAR(requests) set [_id, 0]; | ||
[_request select 0, _data] call (_request select 1); | ||
nil |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,50 @@ | ||
/* ---------------------------------------------------------------------------- | ||
Function: CBA_fnc_promise_create | ||
|
||
Description: | ||
Creates and executes a new Promise. | ||
|
||
Parameters: | ||
_receiver - remoteExecCall target. <NUMBER, OBJECT, STRING, SIDE, GROUP, ARRAY> | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The argument should be called _target. Although _receiver is not used much (anywhere?), it better describes what the target becomes on the target machine. So _function may use the identifier _receiver. Generally everyone uses _target on sender and receiver though. |
||
_function - either string (functionname) or code to execute on target. <STRING, CODE> | ||
_functionArgs - custom arguments to pass to the target. <ANY> | ||
_args - args to pass to the callback (see next param) <ANY> | ||
_callback - callback for the promise (executed on current machine). <CODE> | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If funcArgs comes after func, why does callbackArgs come before callback?
|
||
Will receive an array, with index 0 being what is passed include | ||
_args and index 1 being whatever is returned by the target invokation | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Spelling "invocation". |
||
[_args, _mthdResult] | ||
|
||
Returns: | ||
Identifier that allows to check if a promise is yet done. See CBA_fnc_promise_done. <ARRAY> | ||
|
||
Example: | ||
(begin example) | ||
[ | ||
random_player, "random_function", [], | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Bad use of "random". Should be "arbitrary" or just leave it out. I also don't like how the example does not work when cut and pasted. Maybe use an actual function instead or define one in the example. |
||
[_someLocalVariable], { | ||
params ["_args", "_result"]; | ||
_args params ["_someLocalVariable"]; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. rogue space |
||
diag_log _result; | ||
diag_log _someLocalVariable; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If this were systemChat str [_result]; the example would show me a result in game. |
||
} | ||
] call CBA_fnc_promise_create; | ||
(end) | ||
|
||
Author: | ||
X39 | ||
---------------------------------------------------------------------------- */ | ||
#include "script_component.hpp" | ||
params ["_receiver", "_function", "_functionArgs", "_args", "_callback"]; | ||
private _stamp = diag_tickTime; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Should be noted then that this framework breaks on servers that run for 11 days. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. diag_tickTime is only used to get some value that changes enough to allow reusage of the same slots and checking in There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is an absolute no go and doesn't even guarantee that there are no collisions, especially after diag_tickTime exceeded the floating point precission after 11 days. This should be a counter, possibly as string prepended with the client id (CBA_clientOwner should be a safe way to get it) to make this work in mp. |
||
private _index = 0; | ||
isNil { | ||
_index = GVAR(requests) find 0; | ||
if (_index == -1) then { | ||
_index = GVAR(requests) pushBack [_args, _callback, _stamp]; | ||
} | ||
else { | ||
GVAR(requests) set [_index, [_args, _callback, _stamp]]; | ||
} | ||
}; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. CBA generally does not require thread safety, because writing thread safe code is a pipe dream. If a function should be atomic regardless, for example if it is supposed to be API used by the scrubs/mission makers, then we/(I?) just use this construct instead: https://github.com/CBATeam/CBA_A3/blob/master/addons/settings/fnc_set.sqf#L27-L30 No reason to shit up the code for the scheduler. |
||
[_index, _function, _functionArgs] remoteExec [QGVAR(requests), _receiver, false]; | ||
[_index, _stamp] |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
/* ---------------------------------------------------------------------------- | ||
Function: CBA_fnc_promise_done | ||
|
||
Description: | ||
Checks if a given promise was processed yet. | ||
|
||
Parameters: | ||
_promiseHandle - Handle returned by CBA_fnc_promise_create <ARRAY> | ||
|
||
Returns: | ||
Boolean, true if it is done yet, false if it is not. <BOOL> | ||
|
||
Example: | ||
(begin example) | ||
_promiseHandle call CBA_fnc_promise_done; | ||
(end) | ||
|
||
Author: | ||
X39 | ||
---------------------------------------------------------------------------- */ | ||
#include "script_component.hpp" | ||
params ["_index", "_stamp"]; | ||
private _promise = GVAR(requests) select 0; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why does it get a promise from a list of requests? |
||
_promise isEqualTo 0 || {_promise select 2 != _stamp} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
/* ---------------------------------------------------------------------------- | ||
Function: CBA_fnc_promise_init | ||
|
||
Description: | ||
Initializes the required variables for the promise system. | ||
|
||
Parameters: | ||
Nothing | ||
|
||
Returns: | ||
Nothing | ||
|
||
Example: | ||
(begin example) | ||
[] call CBA_fnc_promise_init; | ||
(end) | ||
|
||
Author: | ||
X39 | ||
---------------------------------------------------------------------------- */ | ||
#include "script_component.hpp" | ||
isNil { | ||
if isNil QGVAR(requests) then { | ||
GVAR(requests) = []; | ||
}; | ||
}; | ||
|
||
nil | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This function seems like bloat to me. Just run this in preInit and tell people to add requiredAddons if they really need this in preInit as well. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I am not aware of how to realize that with the macros in CfgFunctions.hpp There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Just put it in XEH preInit. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This whole function should be nuked and the default of The benefit of preInit is one less if-operation per function call (neglible honestly). The benefit of defining it on demand is that this makes |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
/* ---------------------------------------------------------------------------- | ||
Function: CBA_fnc_promise_receiver | ||
|
||
Description: | ||
Function that gets called when a sender has a request. | ||
|
||
WARNING! Not intended to be called by client-code! | ||
|
||
Parameters: | ||
_id - the promise ID, local to the sender. <ARRAY> | ||
_function - The function to execute, either string (var name) or code. <STRING, CODE> | ||
_args - Arguments to pass to the function. <ANY> | ||
|
||
Returns: | ||
Nothing | ||
|
||
Example: | ||
Nothing | ||
|
||
Author: | ||
X39 | ||
---------------------------------------------------------------------------- */ | ||
#include "script_component.hpp" | ||
|
||
params ["_id", "_function", "_args"]; | ||
private _res = if (_function isEqualType "") then { | ||
_args call (missionNamespace getVariable _function); | ||
} else { | ||
_args call _function; | ||
}; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This control flow is bad: params ["_id", "_function", "_args"];
private _res = if (_function isEqualType "") then {
_args call (missionNamespace getVariable _function);
} else {
_args call _function;
}; Ugly. Ternaries are bad. Good Code should be linear, not branched: params ["_id", "_function", "_args"];
if (_function isEqualType "") then {
_function = missionNamespace getVariable [_function, {}];
};
private _res = _args call _function; Much better. Dunno about the implications of reading arbitrary globals as functions and calling them. Probably a lot of evil that can be done with that. |
||
[_id, _res] remoteExec [QGVAR(requests), remoteExecutedOwner, false]; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Last time I checked, the RE target id and the return value of REOwner do not match up in loaded local hosted multiplayer games, so this is not safe. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. What do you suggest as alternative? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Does this even work? Seems to me that We don't use RE in CBA or ACE, but events instead. |
||
nil |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
MIT License | ||
|
||
Copyright (c) 2018 Marco Silipo (X39) | ||
|
||
Permission is hereby granted, free of charge, to any person obtaining a copy | ||
of this software and associated documentation files (the "Software"), to deal | ||
in the Software without restriction, including without limitation the rights | ||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||
copies of the Software, and to permit persons to whom the Software is | ||
furnished to do so, subject to the following conditions: | ||
|
||
The above copyright notice and this permission notice shall be included in all | ||
copies or substantial portions of the Software. | ||
|
||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | ||
SOFTWARE. |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
#define COMPONENT promise | ||
#include "\x\cba\addons\main\script_mod.hpp" | ||
|
||
#include "\x\cba\addons\main\script_macros.hpp" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
rogue change