Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings
Discussion options

I'm glad you can see my little question. While reading the StateManagement section of the code, I found that there is a variable of type std:: sharedfuture in the StateClient class that indicates whether the functional group setting request was successfully processed (if there are any unprocessed requests, an error will be thrown).In my understanding, the Setstate function of this class is the key to sending requests to EM.
{if (mSetStateFuture.valid())
{...
mSetStatePromise = std::promise();}
mSetStateFuture =getFuture(mSetStatePromise, cSetStateId, _rpcPayload);}
If the first run or previous functional group state change request is satisfied, the program will not go into the if loop and then pass mSetStateFuture into the getFuture function.
{std::shared_future _result{promise.get_future()};
mRpcClient->Send(cServiceId, methodId, cClientId, rpcPayload);
return result;}
In the getFuture function, a variable of type std:: sharedfurture
Result is bound to promise and assigned to mSetStateFuture in the SetState function. My problem is that after the first binding, there is no operation on the future value, such as future. get(), which makes the variable mSetStateFuture unable to be empty. I see that the callback function genericHandler can operate on promise, but such an operation cannot clear future.In StateManagement. h, I saw that there is a checkFuture function that takes values from a future, but it does not seem to work on the StateClient.
If possible, I would like to know how the future and promise are changed and updated when SM sends a request to EM to change the status of the functional group. (My expression may not be very accurate. Future actually represents a variable of type std:: shared_future, while promise represents a variable of type std:: promise.)

You must be logged in to vote

The responsibility is at the callee (StateClient) side and not the caller (SM) side (if you are thinking about which responsibility, then read my previous response again). That is why mSetStateFuture is private and that is why I said previously:

Then, better to put SM outside of this equation to avoid any confusion for now.

Besides that, the idea of that:

mSetStateFuture.valid() should be false

is not correct because if the future is valid, it means the StateClient should first cancel the previous request and inform this cancellation to the callers. And then it should process the new state. Invalid mSetStateFuture means nobody called SetState. So, after the first call, mSetStateFuture

Replies: 2 comments · 1 reply

Comment options

Most of these hassles is because of the following requirement (and maybe also the asynchronous handling of setting a state):
image

If a new requested comes by, the previously sent request should be cancelled.

Now lets dive into the code: First of all std::shared_future is used instead of std::future intentionally so by calling the get method on the future object from any thread, the object still stays valid. If future object was a type of std::future, the first call of get method makes the object invalid. So, by that statement, checkFuture on SM cannot have any affect on the StateClient. Then, better to put SM outside of this equation to avoid any confusion for now.

Now lets get back to StateClient and take a look to the following code:

            if (mSetStateFuture.valid())
            {
                try
                {
                    const ExecErrc cExecErrc{ExecErrc::kCancelled};
                    setPromiseException(mSetStatePromise, cExecErrc);
                }
                catch (std::future_error)
                {
                    // Catch the exception if the promise is already set
                }

                mSetStatePromise = std::promise<void>();
            }

            std::vector<uint8_t> _rpcPayload;
            state.Serialize(_rpcPayload);
            mSetStateFuture =
                getFuture(mSetStatePromise, cSetStateId, _rpcPayload);

            return mSetStateFuture;

As you said, by calling the method for the first time, the if-statement will be skipped, and before return, mSetStateFuture becomes valid. However, (surprisingly) mSetStateFuture will be kept valid even if the state has been set already on EM and it has been notified back via setStateHandler. But why? Because when StateClient returns the future, it only has control of when to set the future value via the corresponding promise, but it does not have any clue when somebody may get that value.

So, if StateClient invalidates the future, it is actually breaking the promise without notifying the owners of the future-copy (those who have already called SetState). However, if somebody calls SetState again in this moment, StateClient is going to tell to the previous callers that:

if you guys get the value of the future (that you have already owned) from this moment, you will get the kCancelled exception (because you are too late now and I need to process a new request).

Then it renews the promise mSetStatePromise = std::promise<void>() and then it renews the future mSetStateFuture = getFuture(mSetStatePromise, cSetStateId, _rpcPayload); and it returns the future object to the current caller.

You must be logged in to vote
0 replies
Comment options

I roughly understand what you mean. Does mSetStateFuture need to be set to empty by the caller? But this is a private member variable, so how can it be changed? In other words, how should the actual code be executed to ensure that the condition if (mSetStateFuture.valid()) is always false?

You must be logged in to vote
1 reply
@langroodi
Comment options

The responsibility is at the callee (StateClient) side and not the caller (SM) side (if you are thinking about which responsibility, then read my previous response again). That is why mSetStateFuture is private and that is why I said previously:

Then, better to put SM outside of this equation to avoid any confusion for now.

Besides that, the idea of that:

mSetStateFuture.valid() should be false

is not correct because if the future is valid, it means the StateClient should first cancel the previous request and inform this cancellation to the callers. And then it should process the new state. Invalid mSetStateFuture means nobody called SetState. So, after the first call, mSetStateFuture should be valid always.

Answer selected by Emanonvvv
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Category
🙏
Q&A
Labels
None yet
2 participants
Morty Proxy This is a proxified and sanitized view of the page, visit original site.