Skip to content
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

Implementation of move semantics for Firebird::string #8059

Merged
merged 8 commits into from
Apr 1, 2024

Conversation

Noremos
Copy link
Contributor

@Noremos Noremos commented Mar 25, 2024

The Firebird project defines "modern C++" features the ones introduced since C++17. Move semantics is already 10 years old, but it is still avoided in code. It would be nice to start implementing it at least in strings.
Pools are difficult to manage in the case of Move semantics, so moving is possible within the same pool.

@AlexPeshkoff AlexPeshkoff self-assigned this Mar 25, 2024
@@ -0,0 +1,146 @@
#include "boost/test/unit_test.hpp"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is class string test src/common/classes/misc/string_test.cpp. It's very old (like string itself) and definitely does not use boost-related features, but there are checks for most of existing functions in the class. May be instead adding separate test it's better to have single one, sooner of all using boost.

PS. I think keeping performance comparison with std::basic_string does not make sense currently and may be cleaned out. First of all because our string is almost never used in performance-critical paths of execution.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have moved the old test to the Boost Test Library. Some tests for the comparison method do not pass.

PathName c = "Aa";
PathName d = "AB";
check(c.compare(d), -1);

StringTest.cpp(530): error: in "StringSuite/StringFunctionalTests/CompareTests1": check c.compare(d) == -1 has failed [7967 != -1]

The result is expected to be 0, -1 or 1, but in reality some positive value is obtained -just like, the result of the memcmp function.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

May be use something like:
check(sign(c.compare(d)), -1);

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok, but originally I wanted to know if the compare method returns the value correctly. From your answer I understand that yes, the problem is in too old test. I will fix it

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

PS. I think keeping performance comparison with std::basic_string does not make sense currently and may be cleaned out. First of all because our string is almost never used in performance-critical paths of execution.

BTW, if it is not used in performance-critical places, why not to drop them and use std::string instead?

@AlexPeshkoff
Copy link
Member

AlexPeshkoff commented Mar 27, 2024 via email

@aafemt
Copy link
Contributor

aafemt commented Mar 27, 2024

Move semantic requires to leave source in valid but undetermined state. There is no point to use exchange in constructor because target is empty and three exchanges in row is not atomic anyway.

@@ -754,6 +782,14 @@ namespace Firebird
{
return add(&c, 1);
}
StringType& operator=(StringType&& rhs)
{
if (!baseMove(std::forward<AbstractString>(rhs)))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here you trash memory replacing valid bufferSize with INLINE_BUFFER_SIZE.

@AlexPeshkoff
Copy link
Member

AlexPeshkoff commented Mar 27, 2024 via email

@aafemt
Copy link
Contributor

aafemt commented Mar 27, 2024

I'm talking about deriving Firebird::string from std::string adding necessary functions and replacing those that differ from standard by name only. The result would have better portability and new standard features (like this move semantic) will be available out-of-box.

@Noremos
Copy link
Contributor Author

Noremos commented Mar 28, 2024

Move semantic requires to leave source in valid but undetermined state

I'm sorry, but I didn't understand you very well. Are you suggesting to delete these 2 lines?

stringLength = std::exchange(rhs.stringLength, 0);
bufferSize = std::exchange(rhs.bufferSize, INLINE_BUFFER_SIZE);

@aafemt
Copy link
Contributor

aafemt commented Mar 28, 2024

I'm suggesting to delete whole baseMove() performing minimal needed operations individually. Move constructor do not have to require initialization of member of this - it is a waste of time.

@AlexPeshkoff
Copy link
Member

AlexPeshkoff commented Mar 28, 2024 via email

@Noremos
Copy link
Contributor Author

Noremos commented Mar 29, 2024

should be enough, but I prefer to be on the safe side and keep the code resetting move source to empty state.

Using a moved variable is not recommended, but it is still a permitted approach, so I agree with you that it is better to to keep a source string in its ready-to-use state. I believe the optimizer will omit these extra lines if necessary

@AlexPeshkoff AlexPeshkoff merged commit 2d8c006 into FirebirdSQL:master Apr 1, 2024
20 of 24 checks passed
@@ -0,0 +1,3 @@
char lbl[] = "0123456789";
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This test is failing in Android builds (https://github.com/FirebirdSQL/firebird/actions/runs/8513177447/job/23316639529)

It does not look as a good practice to reference this file based in the source path.

I think it's better to create this file as temporary file in runtime inside the test.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry, missed this check.
Is it allowed to use std::filesystem in tests and the android build?

namespace fs = std::filesystem;
auto tempFilePath = fs::temp_directory_path() / "test.txt";
```

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I hope it is. It should be present in ndk 22b and we are using 25b.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should I create a new PR or do you just cherry pick my postfix?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

New PR, please.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Noremos pushed a commit to red-soft-ru/firebird that referenced this pull request Apr 2, 2024
Noremos pushed a commit to red-soft-ru/firebird that referenced this pull request Apr 2, 2024
asfernandes pushed a commit that referenced this pull request Apr 2, 2024
Co-authored-by: Artyom Abakumov <artyom.abakumov@red-soft.ru>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

5 participants