Skip to content

Prepare Bareos for an upgrade to the C++20 standard#1271

Merged
arogge merged 21 commits intobareos:masterfrom
alaaeddineelamri:dev/alaaeddineelamri/master/s5285-upgrade-to-cpp20-standard
Nov 7, 2022
Merged

Prepare Bareos for an upgrade to the C++20 standard#1271
arogge merged 21 commits intobareos:masterfrom
alaaeddineelamri:dev/alaaeddineelamri/master/s5285-upgrade-to-cpp20-standard

Conversation

@alaaeddineelamri
Copy link
Contributor

@alaaeddineelamri alaaeddineelamri commented Oct 5, 2022

Thank you for contributing to the Bareos Project!

Description

This PR will upgrade Bareos to use the C++20 standard.

Please check

  • Short description and the purpose of this PR is present above this paragraph
  • Your name is present in the AUTHORS file (optional)

If you have any questions or problems, please give a comment in the PR.

Helpful documentation and best practices

Checklist for the reviewer of the PR (will be processed by the Bareos team)

General
  • PR name is meaningful
  • Purpose of the PR is understood
  • Commit descriptions are understandable and well formatted
  • Check backport line
  • Is the PR title usable as CHANGELOG entry?
  • Separate commit for CHANGELOG.md ("update CHANGELOG.md"). The PR number is correct.
Source code quality
  • Source code changes are understandable
  • Variable and function names are meaningful
  • Code comments are correct (logically and spelling)
  • Required documentation changes are present and part of the PR
  • bareos-check-sources --since-merge does not report any problems

@alaaeddineelamri alaaeddineelamri force-pushed the dev/alaaeddineelamri/master/s5285-upgrade-to-cpp20-standard branch 2 times, most recently from f234b52 to 4cbd561 Compare October 7, 2022 12:24
status_ = Status::kWaiting;
bool success = cond_variable_.wait_for(ul, ms, [=]() { return notified; });
bool success
= cond_variable_.wait_for(ul, ms, [=, this]() { return notified; });
Copy link
Member

Choose a reason for hiding this comment

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

i guess you could just capture notified

Copy link
Contributor Author

Choose a reason for hiding this comment

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

creates this error:

bareos/core/src/tests/thread_list.cc:61: error: capture of non-variable ‘WaitCondition::notified’
bareos/core/src/tests/thread_list.cc: In member function ‘void WaitCondition::WaitFor(std::chrono::milliseconds)’:
bareos/core/src/tests/thread_list.cc:61:19: error: capture of non-variable ‘WaitCondition::notified’

this must be captured.
capturing this->notified doesn't work either.

Copy link
Member

Choose a reason for hiding this comment

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

you're right, but you don't need to capture = then.

@arogge arogge self-assigned this Oct 13, 2022
@alaaeddineelamri alaaeddineelamri marked this pull request as ready for review October 13, 2022 11:45
@alaaeddineelamri alaaeddineelamri marked this pull request as draft October 21, 2022 17:09
@alaaeddineelamri alaaeddineelamri force-pushed the dev/alaaeddineelamri/master/s5285-upgrade-to-cpp20-standard branch 2 times, most recently from 240ca7f to 642ecc3 Compare October 24, 2022 11:05
@alaaeddineelamri alaaeddineelamri marked this pull request as ready for review October 24, 2022 11:38
@alaaeddineelamri alaaeddineelamri force-pushed the dev/alaaeddineelamri/master/s5285-upgrade-to-cpp20-standard branch from 642ecc3 to 3c20a73 Compare October 25, 2022 12:24
@alaaeddineelamri alaaeddineelamri force-pushed the dev/alaaeddineelamri/master/s5285-upgrade-to-cpp20-standard branch from 3c20a73 to 42b43e1 Compare October 25, 2022 15:59
Comment on lines 53 to 54
# switch on CXX 17 Support
#
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
# switch on CXX 17 Support
#

timer_start = 0; /* clear timer */
if (rc != pktsiz) {
errors++;
errors = errors + 1;
Copy link
Member

Choose a reason for hiding this comment

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

The atomic has working operator++()

Suggested change
errors = errors + 1;
++errors;

b_errno = errno;
}
errors++;
errors = errors + 1;
Copy link
Member

Choose a reason for hiding this comment

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

The atomic has working operator++()

Suggested change
errors = errors + 1;
++errors;

timer_start = 0; /* clear timer */
if (nbytes != header_length) {
errors++;
errors = errors + 1;
Copy link
Member

Choose a reason for hiding this comment

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

The atomic has working operator++()

Suggested change
errors = errors + 1;
++errors;

b_errno = errno;
}
errors++;
errors = errors + 1;
Copy link
Member

Choose a reason for hiding this comment

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

The atomic has working operator++()

Suggested change
errors = errors + 1;
++errors;

Comment on lines 263 to +266
VolumeReservationItem* vol;
VolumeReservationItem emptyVol;

vol = (VolumeReservationItem*)malloc(sizeof(VolumeReservationItem));
*vol = emptyVol;
vol = new (vol) VolumeReservationItem(); /* placement new instead of memset */

Copy link
Member

Choose a reason for hiding this comment

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

This is one of the places that we can actually improve a lot with C++20.
An obvious one is:

auto* vol = static_cast<VolumeReservationItem*>(malloc(sizeof(VolumeReservationItem)));
std::construct_at(vol);

The two functions below FreeVolItem(), FreeReadVolItem() are identical, so we should probably remove the latter one.

Having said that, I think optimal code for this function would look like:

auto* vol = new VolumeReservationItem(VolumeName, dcr);

With all the setup and teardown moved into proper a ctor and dtor.

What is currently stopping us from doing that is that the volume list is a dlist<VolumeReservationItem> and that dlist<>::destroy() always uses free(n) to simply free the memory.
So if we extended dlist<T> to dlist<T, use_delete = false> and changed dlist<>::destroy() to honor that flag and use delete instead of free() we could then add a ctor/dtor to VolumeReservationItem, simplifying new_vol_item(), FreeVolItem(), FreeReadVolItem(), dup_vol_list() and FreeVolumeList() a lot.

However, after reading what I just wrote, this may be better suited for another cleanup PR.

Copy link
Contributor Author

@alaaeddineelamri alaaeddineelamri Oct 28, 2022

Choose a reason for hiding this comment

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

I had somewhat of the same idea here at least in the sense of just using new and trying to replace the free with a delete somewhere or a destructor, but I ended up with the same conclusion that those changes would probably require more work than simply complying with c++20 standards

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Certain compilers we use in our containers seem to not support std::construct_at

Copy link
Member

Choose a reason for hiding this comment

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

That's bad. std::construct_at() is part of C++20. If a compiler or library doesn't support it, we don't have real C++20 support there.
Maybe we can move to even newer compilers/libraries on the affected platforms?

I cannot find construct_at() as a feature on cppreference's compiler support page. However, there are a lot of features that require at least GCC 10 or even GCC 11.
At least for RHEL 7 and RHEL 8 we're on GCC 8 right now, which seems to be way too old for C++20.

Comment on lines +81 to +82
void IncUseCount(void) { use_count_++; }
void DecUseCount(void) { use_count_--; }
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
void IncUseCount(void) { use_count_++; }
void DecUseCount(void) { use_count_--; }
void IncUseCount(void) { ++use_count_; }
void DecUseCount(void) { --use_count_; }

status_ = Status::kWaiting;
bool success = cond_variable_.wait_for(ul, ms, [=]() { return notified; });
bool success
= cond_variable_.wait_for(ul, ms, [=, this]() { return notified; });
Copy link
Member

Choose a reason for hiding this comment

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

you're right, but you don't need to capture = then.

Device() = default;
virtual ~Device();
Device* volatile swap_dev{}; /**< Swap vol from this device */
Device* swap_dev{}; /**< Swap vol from this device */
Copy link
Member

Choose a reason for hiding this comment

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

Hmm... that's a tough one. Basically, if the code ran on C++11 and later with volatile it should also run fine without volatile.
We could probably make this a std::atomic<Device*>, but I don't think that is required.

JobControlRecord* jcr{}; /**< Pointer to JobControlRecord */
pthread_mutex_t mutex_ = PTHREAD_MUTEX_INITIALIZER; /**< Access control */
pthread_mutex_t r_mutex = PTHREAD_MUTEX_INITIALIZER; /**< rLock pre-mutex */
Device* volatile dev{}; /**< Pointer to device */
Copy link
Member

Choose a reason for hiding this comment

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

This does indeed produce different assembler code in some translation units. However, I don't see how not using volatile here should lead to an issue.

@alaaeddineelamri alaaeddineelamri force-pushed the dev/alaaeddineelamri/master/s5285-upgrade-to-cpp20-standard branch 2 times, most recently from 0861754 to b4cbcbf Compare October 28, 2022 17:41
@alaaeddineelamri alaaeddineelamri changed the title Upgrade Bareos to use the C++20 standard Prepare Bareos for an upgrade to the C++20 standard Nov 7, 2022
@arogge arogge force-pushed the dev/alaaeddineelamri/master/s5285-upgrade-to-cpp20-standard branch 3 times, most recently from dbef0a9 to bebe040 Compare November 7, 2022 14:36
@arogge arogge force-pushed the dev/alaaeddineelamri/master/s5285-upgrade-to-cpp20-standard branch 3 times, most recently from 442b2a4 to 7c74b46 Compare November 7, 2022 15:03
Alaa Eddine Elamri and others added 15 commits November 7, 2022 17:16
volmgr


vol_mgr: use std::construct_at instead of placement new
replace problematic accesses to JobStatus with getter
Certain compilers we use in our containers seem to not support std::construct_at
C++20 supports designated initializers. However, it doesn't allow
mixing of named and unnamed initialization. As we need to use the
PyVarObject_HEAD_INIT() macro, which doesn't name the attributes it
sets, we have to downgrade the compiler to C++17, so designated
initializers are handled as compiler extension, which will allow the
mixing that occurs here.

See also: python/cpython#99202
@arogge arogge force-pushed the dev/alaaeddineelamri/master/s5285-upgrade-to-cpp20-standard branch from 7c74b46 to 3922775 Compare November 7, 2022 16:17
@arogge arogge merged commit 43dea81 into bareos:master Nov 7, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants