Compare-and-Swap over POSIX-compliant filesystem objects
Interview Questions practice on Codemia
Over 8,000 real interview questions from top companies, searchable by company and role.
Introduction
There is no standard POSIX system call that gives you a true memory-style compare-and-swap operation over arbitrary filesystem objects. What POSIX does give you are a few atomic building blocks, especially rename, link, mkdir, and open with exclusive-creation semantics, and you combine those to approximate optimistic concurrency or atomic replacement.
Why Filesystem CAS Is Harder Than Memory CAS
In memory, compare-and-swap means "replace value X with value Y only if the current value is still X." That is a single primitive operating on one memory location.
Filesystems are different:
- file contents may be large, not one machine word
- metadata and data may change independently
- POSIX atomicity guarantees are narrower than people assume
- many operations are atomic only for names, not for full content validation
So the honest answer is that POSIX filesystems do not expose a general-purpose CAS primitive over file contents.
What POSIX Does Guarantee Well: Atomic Rename
The strongest common building block is atomic replacement through rename. If you write new data to a temporary file and then rename it over the old path on the same filesystem, other processes see either the old file or the new file, not a half-written mixture.
This gives atomic replace, which is often what people actually need. But notice the missing part: there is no built-in compare step that checks whether current.txt still has an expected version before the replace happens.
Simulating CAS with Versioned Names
A common pattern is to store immutable versions under unique names and then atomically switch a pointer-like filename.
For example:
- read the current version marker
- write a new file with a new version name
- atomically rename a reference file or symlink to point at the new version
- fail if the expected old version is no longer current
This is not a single POSIX CAS instruction, but it approximates optimistic concurrency if you keep version information separate from the payload.
Exclusive Creation as a Coordination Primitive
Another useful tool is open with O_CREAT | O_EXCL, which creates a file only if it does not already exist.
This is useful for leader election, one-writer claims, and coarse-grained optimistic coordination. It is not full compare-and-swap over file content, but it is a standard atomic filesystem primitive that solves many practical races.
Directory Creation as an Atomic Claim
mkdir is also commonly used as an atomic claim mechanism because creating a directory either succeeds or fails if the path already exists.
This works well in shell scripts and simple operational tooling. Again, it is not a byte-level CAS. It is a name-based atomic ownership pattern.
What You Cannot Rely On
You should not assume that reading a file, comparing its content in user space, and then writing back a replacement is atomic. Another process can always change the file between your read and write unless you add coordination.
So the naive pattern:
- read file
- compare expected content
- write file if unchanged
is not safe by itself under concurrency.
To make it safe, you usually need one of:
- a lock file or directory lock
- atomic rename around versioned content
- advisory locking such as
fcntl - a higher-level database or coordination service
Common Pitfalls
- Assuming POSIX provides a built-in compare-and-swap syscall for file contents.
- Treating atomic
renameas though it also performs a compare step. - Reading and rewriting a file optimistically without any locking or version check.
- Forgetting that
renameatomicity depends on staying within the same filesystem. - Expecting name-level atomicity to solve every content-level concurrency problem.
Summary
- POSIX does not provide a general CAS primitive over filesystem objects.
- Atomic
renameis the main tool for safe replace operations. - '
open(..., O_CREAT | O_EXCL)andmkdirare useful atomic claim primitives.' - To approximate CAS, combine versioning, locks, and atomic name updates.
- If you need stronger compare-and-update guarantees, a database or coordination service is often the better abstraction.
Related reading
- Compare and swap C0x
- Compare two MySQL databases
- CompletableFuture in loop How to collect all responses and handle errors
- CompletableFuture not working as expected
- CompletableFuture thenApply vs thenCompose
- CompletableFuture vs Async
- CompletableFuture vs Spring Transactions
- CompletableFutureT class join vs get
.png&w=3840&q=75)
Tackling System Design Interview Problems
A short course that equips you with the skills to approach system design interviews methodically.
Start the free courseTrack what you have practised
A free account saves your progress, solutions and study plan across every problem on Codemia.
Interview Questions practice on Codemia
Over 8,000 real interview questions from top companies, searchable by company and role.