Skip to content

chore(atomic): Implement VC6 atomic compatibility template class - #3325

Open
Mauller wants to merge 1 commit into
TheSuperHackers:mainfrom
Mauller:Mauller/feat-atomic-compat
Open

Mauller wants to merge 1 commit into
TheSuperHackers:mainfrom
Mauller:Mauller/feat-atomic-compat

Conversation

@Mauller

@Mauller Mauller commented Sep 20, 2026 •

Copy link
Copy Markdown

Closes: #887

This PR implements a set of std atomic like VC6 template classes.

This will allow the use of std::atomic<type>variable; in vc6 code, allowing the cleanup and replacement of legacy ASM in places such as the mutex classes.

Internally the template classes use a long variable and the windows interlocked functions which only work with the long type.
This will result in more memory usage in VC6 builds but will provide a cleaner interface and transition to std::atomic in other compilers.

Currently the only supported types, including their unsigned variants, are; long int short, char and bool where the bool type has a more limited interface similar to how it is implemented in the std library.

Edit - This is designed to just work with base types where atomic reference counting or an atomic boolean is required.
Using atomic trivial custom classes will have to be done when VC6 is dropped.


The contents of this PR were initially templated using AI then fixed up and extended by a living munkee.

Edit - Further work with LLM assistance consolidated the template specialisations into a generic template with specialise atomic_trait structs that limit the supported types.

For the AI's reviewing, this is meant to be within the std namespace to allow the use of the real std library outside of VC6 code. This is okay to do in VC6 builds as atomic does not exist within VC6 and C++98. This then allows a single implementation at the site of use that works directly with the std libraries atomic.

@Mauller Mauller self-assigned this Sep 20, 2026
@Mauller Mauller added Enhancement Is new feature or request Gen Relates to Generals ZH Relates to Zero Hour Major Severity: Minor < Major < Critical < Blocker labels Sep 20, 2026
@coderabbitai

coderabbitai Bot commented Sep 20, 2026 •

Copy link
Copy Markdown

Review in Change Stack →

Navigate logical layers of code changes, visualize relationships, and explore their blast radius.

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • ✅ Review completed - (🔄 Check again to review again)

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Advanced

Run ID: 42756a0c-5462-4ee6-b793-2a375b938160

📥 Commits

Reviewing files that changed from the base of the PR and between 040d75b and fd33e87.

📒 Files selected for processing (2)
  • Dependencies/Utility/Utility/atomic_compat.h
  • Dependencies/Utility/Utility/interlocked_adapter.h

Included review availability: This review used your included allowance. Your plan provides up to 10 included reviews per hour; 9 remain after this review.


Walkthrough

The pull request adds a legacy compiler implementation of std::atomic for listed integer types and bool. Other configurations include <atomic>. Legacy interlocked wrappers support the atomic implementation.

Changes

Atomic Compatibility

Layer / File(s) Summary
Compatibility foundation
Dependencies/Utility/Utility/atomic_compat.h, Dependencies/Utility/Utility/interlocked_adapter.h
Selects the standard or legacy implementation, defines integer conversion traits, and adds legacy InterlockedExchange and InterlockedExchangeAdd wrappers.
Numeric atomic implementation
Dependencies/Utility/Utility/atomic_compat.h
Adds generic integral atomic operations backed by interlocked operations, including load, store, exchange, compare-exchange, arithmetic, and bitwise operations.
Boolean atomic specialization
Dependencies/Utility/Utility/atomic_compat.h
Adds interlocked load, store, exchange, and compare-exchange operations for std::atomic<bool>, plus assignment, conversion, negation, and equality comparisons.

Priority: ⬇️ Low

Estimated code review effort: 3 (Moderate) | ~20 minutes

Change: Feature

Merge Risk: ⚪ Minimal · up to fd33e

The identified VC6 compatibility and short-operator risks are addressed at the current head. No actionable issue remains from this review.

🚥 Pre-merge checks | ✅ 3 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Linked Issues check ⚠️ Warning Issue #887 requires cross-compatible interlocked increment and decrement helper functions. The current interlocked_adapter.h defines InterlockedCompareExchange, InterlockedExchange, `Interlocked… Add the required operating-system-independent increment and decrement helper APIs. Add the VC6 assembly implementations for the required 16-bit and 64-bit operations. Add automated tests for the helper behavior and the VC6 compatibility pat…
✅ Passed checks (3 passed)
Check name Status Explanation
Out of Scope Changes check ✅ Passed The atomic compatibility classes and interlocked wrappers support the VC6 interlocked and atomic compatibility purpose associated with issue #887. The reviewed changes do not demonstrate an unrelated …
Title check ✅ Passed The title clearly identifies the implementation of a VC6-compatible atomic template class, which is the main change in the pull request.
Description check ✅ Passed The description directly explains the VC6 atomic compatibility classes, supported types, implementation approach, and intended replacement of legacy assembly.
Full details: Linked Issues check

Explanation

Issue #887 requires cross-compatible interlocked increment and decrement helper functions. The current interlocked_adapter.h defines InterlockedCompareExchange, InterlockedExchange, InterlockedExchangeAdd, and pointer wrappers, but no increment or decrement helpers. It also contains no VC6 assembly implementation for 16-bit or 64-bit operations. atomic_compat.h uses 32-bit long storage and CAS loops, so it does not satisfy those helper requirements.

Resolution

Add the required operating-system-independent increment and decrement helper APIs. Add the VC6 assembly implementations for the required 16-bit and 64-bit operations. Add automated tests for the helper behavior and the VC6 compatibility path.


Comment @coderabbitai help to get the list of available commands.

@greptile-apps

greptile-apps Bot commented Sep 20, 2026 •

Copy link
Copy Markdown

RetriggerConfidence Score: 5/5

[Medium risk] Adds VC6 compatibility layer for atomic operations.

The PR appears safe to merge based on the reviewed changes and resolved prior findings.

Summary

The PR adds a VC6-compatible std::atomic template backed by Windows interlocked operations and extends the interlocked adapter. Since the previous review, it has made intermediate values in the fetch operations const. The previously reported issues are resolved in the current code.

Reviews (15) · Last reviewed commit: "chore(atomic): Implement VC6 atomic comp..."

Comment thread Dependencies/Utility/Utility/atomic_compat.h Outdated
Comment thread Dependencies/Utility/Utility/atomic_compat.h Outdated
Comment thread Dependencies/Utility/Utility/atomic_compat.h Outdated

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 4


ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Advanced

Run ID: 8b7c73e7-3012-4741-b690-2537e67b3954

📥 Commits

Reviewing files that changed from the base of the PR and between e401710 and c746f90.

📒 Files selected for processing (1)
  • Dependencies/Utility/Utility/atomic_compat.h

Included review availability: Your plan provides up to 10 included reviews per hour; 7 remain after this review.

Comment thread Dependencies/Utility/Utility/atomic_compat.h Outdated
Comment thread Dependencies/Utility/Utility/atomic_compat.h Outdated
Comment thread Dependencies/Utility/Utility/atomic_compat.h Outdated
Comment thread Dependencies/Utility/Utility/atomic_compat.h Outdated
@Mauller
Mauller force-pushed the Mauller/feat-atomic-compat branch from c746f90 to 3d80556 Compare September 20, 2026 09:38
Comment thread Dependencies/Utility/Utility/atomic_compat.h Outdated
@Mauller
Mauller force-pushed the Mauller/feat-atomic-compat branch from 3d80556 to 240f4da Compare September 20, 2026 09:42
@Mauller

Mauller commented Sep 20, 2026

Copy link
Copy Markdown
Author

@coderabbitai PR updated

@Mauller
Mauller force-pushed the Mauller/feat-atomic-compat branch from 240f4da to c75098e Compare September 20, 2026 09:50

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🧹 Nitpick comments (1)
Dependencies/Utility/Utility/atomic_compat.h (1)

44-52: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Add memory_order parameters to keep the two branches source compatible.

The VC6 specializations expose load(), store(), exchange(), fetch_*() and compare_exchange_*() without a memory-order argument. Shared code that compiles on both branches cannot write flag.load(std::memory_order_acquire) or counter.fetch_add(1, std::memory_order_relaxed), because the standard branch accepts those calls and the VC6 branch rejects them. The interlocked functions are already full barriers, so the parameter can be ignored.

Declare a memory_order enum in the VC6 branch and accept a defaulted, unused parameter in each operation.

♻️ Sketch of the compatible signatures
 namespace std
 {
+	enum memory_order
+	{
+		memory_order_relaxed,
+		memory_order_consume,
+		memory_order_acquire,
+		memory_order_release,
+		memory_order_acq_rel,
+		memory_order_seq_cst
+	};
+
 	// Capture unsupported types and error during compilation
 	template<class T>
 	class atomic;
-		long load() const
+		long load(memory_order = memory_order_seq_cst) const
 		{
 			return InterlockedCompareExchange(&value_, 0, 0);
 		}

-		void store(long value)
+		void store(long value, memory_order = memory_order_seq_cst)
 		{
 			InterlockedExchange(&value_, value);
 		}

Apply the same pattern to the short, int and bool specializations.


ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Advanced

Run ID: 20f56eae-b2e9-450d-8ceb-14e570fc10ed

📥 Commits

Reviewing files that changed from the base of the PR and between c746f90 and c75098e.

📒 Files selected for processing (2)
  • Dependencies/Utility/Utility/atomic_compat.h
  • Dependencies/Utility/Utility/interlocked_adapter.h

Included review availability: Your plan provides up to 10 included reviews per hour; 9 remain after this review.

@Mauller

Mauller commented Sep 20, 2026

Copy link
Copy Markdown
Author

@greptile can you update your review as it is invalid now, VC6 interlocked calls do not fail as they are called through the wrapper functions in interlocked_adapter.h

@coderabbitai

coderabbitai Bot commented Sep 20, 2026 •

Copy link
Copy Markdown

@Mauller I will review the updated changes.

⚠️ Action not completed

Already reviewed the last commit. Use @coderabbitai full review to rerun a review of the entire changeset.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@Caball009 Caball009 left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Incomplete review; I haven't paid attention to the complexities of <short>.

I assume the lack of support for unsigned integers is because the win32 atomic functions use LONG everywhere.

Comment thread Dependencies/Utility/Utility/atomic_compat.h Outdated
Comment thread Dependencies/Utility/Utility/atomic_compat.h Outdated
@Mauller
Mauller force-pushed the Mauller/feat-atomic-compat branch from c75098e to 040d75b Compare September 20, 2026 14:08
@coderabbitai
coderabbitai Bot requested a review from Caball009 September 20, 2026 14:09

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 1


ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Advanced

Run ID: 7cdb97ac-d4ac-4dcb-8b00-9b81a533e1f8

📥 Commits

Reviewing files that changed from the base of the PR and between c75098e and 040d75b.

📒 Files selected for processing (1)
  • Dependencies/Utility/Utility/atomic_compat.h

Included review availability: Your plan provides up to 10 included reviews per hour; 9 remain after this review.

Comment thread Dependencies/Utility/Utility/atomic_compat.h Outdated
@Mauller
Mauller force-pushed the Mauller/feat-atomic-compat branch 2 times, most recently from c5d2c7e to 55b08e5 Compare September 20, 2026 15:29

@xezon xezon left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

It would be nice if this was tested for correctness side by side with real std::atomic. Claude et al could do that.

Comment thread Dependencies/Utility/Utility/atomic_compat.h Outdated
Comment thread Dependencies/Utility/Utility/atomic_compat.h Outdated
Comment thread Dependencies/Utility/Utility/atomic_compat.h Outdated
@Mauller
Mauller force-pushed the Mauller/feat-atomic-compat branch from 55b08e5 to 40fdb4d Compare September 20, 2026 17:05
Comment thread Dependencies/Utility/Utility/interlocked_adapter.h Outdated

@xezon xezon left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

The template can be simplified.

Comment thread Dependencies/Utility/Utility/atomic_compat.h Outdated
Comment thread Dependencies/Utility/Utility/atomic_compat.h Outdated
Comment thread Dependencies/Utility/Utility/atomic_compat.h Outdated
Comment thread Dependencies/Utility/Utility/atomic_compat.h Outdated
Comment thread Dependencies/Utility/Utility/atomic_compat.h Outdated
Comment thread Dependencies/Utility/Utility/atomic_compat.h Outdated
Comment thread Dependencies/Utility/Utility/atomic_compat.h Outdated
{
// Capture unsupported types and error during compilation
template<class T>
class atomic;

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

I don't think it is necessary to make 4 template specializations. Just make 1 template implementation, with encode and decode, which is no-op for long, and identical for all else.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

I can take a look, but bool needs to have a separate implementation as there are numerical operations that make no sense on bool and don't exist on it in the STD implementation. Also there are logical operation on bool that don't exist or make no sense on numeric types.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

You can specialize bool then when needed.

#if !(defined(_MSC_VER) && _MSC_VER < 1300) || __cplusplus >= 201103L
#include <atomic>
#else
#include <windows.h>

@xezon xezon Sep 21, 2026 •

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Always put

#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
#endif

before. Unless it interlocked functions only include without that.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

i could probably drop the windows.h include since it was there for the interlocked functions, but those are now included throught the interlocked adapter.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

The interlocked_adapter does not include windows.h

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

removed windows.h

@Mauller Mauller Sep 22, 2026 •

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Ah i might actually need to include this as it seems that not all places include the windows header that might end up with the atomic compat.

While testing with ascii string, i get errors during compilation that the windows specific types are unidentified within interlocked_adapter.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Hmm, it actually fails to compile if i include

#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
#endif

before windows.h

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

That seems not good. What if someone includes this file after defining WIN32_LEAN_AND_MEAN themselves? This basically happens everywhere in game.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

I have a change coming where all custom WIN32_LEAN_AND_MEAN defines are removed and it is just defined once in precompiled.h

@Mauller
Mauller force-pushed the Mauller/feat-atomic-compat branch from 40fdb4d to d6740d0 Compare September 22, 2026 20:09
@Mauller

Mauller commented Sep 22, 2026

Copy link
Copy Markdown
Author

Updated after doing the house keeping from the various comments.

I will look at trying to make this a bit more generic next.

// This file contains VC6 compatible atomic classes for the long, int, short and bool types
#pragma once

#if !(defined(_MSC_VER) && _MSC_VER < 1300) || __cplusplus >= 201103L

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

How about we use __has_include. I did the same approach for usp10 in #3342

atomic_adapter.h:

#if defined(__has_include)
	#if __has_include(<atomic>)
		#define HAVE_ATOMIC_H 1
	#endif
#endif

#ifdef HAVE_ATOMIC_H
	#include <atomic.h>
#else
	#include "atomic_compat.h"
#endif

@Mauller
Mauller force-pushed the Mauller/feat-atomic-compat branch from d6740d0 to fefbd23 Compare September 27, 2026 08:34
@Mauller

Mauller commented Sep 27, 2026

Copy link
Copy Markdown
Author

Just a rebase on recent main before continuing work

@Mauller
Mauller force-pushed the Mauller/feat-atomic-compat branch from fefbd23 to fd33e87 Compare September 28, 2026 12:04
@Mauller

Mauller commented Sep 28, 2026 •

Copy link
Copy Markdown
Author

A little bit more LLM assistance but i think this one is most of the way there.

The atomic_trait structs are there to provide conversions for the various types and for handling signed calculations in various places with the encode/decodeUnsigned functions.

A lot of places had to use compare and store (CAS) loops to make sure the relevant operations happened in the right places to handle signed overflows and such.

The various atomic_trait struct are also there to limit which types this class can be used with, along with the type conversions being chosen correctly.

@xezon xezon left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Looks promising. I think the overall design is fine.

Comment thread Dependencies/Utility/Utility/atomic_compat.h Outdated
Comment thread Dependencies/Utility/Utility/atomic_compat.h Outdated

T operator^=(T value)
{
T oldValue = fetch_xor(value);

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Minor: can add constness to variables.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

added const to places where it's reasonable to do so

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Still a couple in the exchange loops that could be made const.

Comment thread Dependencies/Utility/Utility/atomic_compat.h Outdated
Comment thread Dependencies/Utility/Utility/atomic_compat.h Outdated
Comment thread Dependencies/Utility/Utility/atomic_compat.h Outdated
Comment thread Dependencies/Utility/Utility/atomic_compat.h
@Mauller
Mauller force-pushed the Mauller/feat-atomic-compat branch from fd33e87 to 7edfbe0 Compare September 28, 2026 21:24
@Mauller

Mauller commented Sep 28, 2026

Copy link
Copy Markdown
Author

Lots of tweaks based on feedback.

Comment thread Dependencies/Utility/Utility/atomic_compat.h Outdated
Comment thread Dependencies/Utility/Utility/atomic_compat.h Outdated
@Mauller
Mauller force-pushed the Mauller/feat-atomic-compat branch from 7edfbe0 to a49a732 Compare September 29, 2026 12:08
@Mauller

Mauller commented Sep 29, 2026 •

Copy link
Copy Markdown
Author

Tweaked.

I do test this by replacing unsigned short m_refCount; in Ascii and Unicode StringData with std::atomic<short> m_refCount; and commenting out the scoped sections

@Mauller
Mauller force-pushed the Mauller/feat-atomic-compat branch from a49a732 to 54e6a21 Compare September 29, 2026 17:40
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Enhancement Is new feature or request Gen Relates to Generals Major Severity: Minor < Major < Critical < Blocker ZH Relates to Zero Hour

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants