Warrior_EA/System/AtomicFile.mqh
AnimateDread b91c7b1f7a refactor(comments): box headers to stdlib length
The //| box blocks were excluded from 0b06f8e and 5efdb48 and were what
remained: 160 of them ran to 10+ lines, the longest to 88. Compressed to their
leading topic sentences - 5 lines for a function header, 8 for a file header -
keeping the box format and the standard MQL5 name/author lines verbatim.

Verified at the BYTE level this time, across every in-scope file: the list of
non-comment lines is byte-identical to HEAD and braces balance. The first check
compared a locale-decoded 'git show' against a UTF-8 read and flagged 25 files
that had not changed at all - every BOM and every non-ASCII line mismatched.

47,696 -> 40,665 lines in scope; comment share 38% -> 26%.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-22 00:30:14 -04:00

52 lines
2.3 KiB
MQL5

//+------------------------------------------------------------------+
//| Warrior_EA |
//| AnimateDread |
//| |
//| Crash-safe binary file writes. |
//+------------------------------------------------------------------+
#ifndef WARRIOR_ATOMIC_FILE_MQH
#define WARRIOR_ATOMIC_FILE_MQH
//+------------------------------------------------------------------+
//| Open a temp file to stage an atomic binary write. |
//+------------------------------------------------------------------+
int AtomicWriteBegin(const string finalName, const int commonFlag, string &tmpName)
{
tmpName = finalName + ".savetmp";
ResetLastError();
return FileOpen(tmpName, commonFlag | FILE_BIN | FILE_WRITE | FILE_SHARE_READ | FILE_SHARE_WRITE);
}
//+------------------------------------------------------------------+
//| Close the staged write and either publish it or discard it. |
//+------------------------------------------------------------------+
bool AtomicWriteEnd(const int handle, const string finalName, const string tmpName,
const int commonFlag, const bool ok, const string context)
{
if(handle != INVALID_HANDLE)
{
FileFlush(handle);
FileClose(handle);
}
//--- A failed/partial write must NEVER touch the real file - discard the temp, keep the last good copy.
if(!ok)
{
FileDelete(tmpName, commonFlag);
Print(context, ": write to ", tmpName, " failed - kept the existing ", finalName,
" intact (no atomic swap performed)");
return false;
}
//--- Atomic swap: FILE_REWRITE lets FileMove replace an existing destination in one operation.
ResetLastError();
if(!FileMove(tmpName, commonFlag, finalName, commonFlag | FILE_REWRITE))
{
Print(context, ": atomic rename ", tmpName, " -> ", finalName, " failed (error ",
IntegerToString(GetLastError()), ") - the temp holds the new content and the existing ",
finalName, " is unchanged");
ResetLastError();
return false;
}
return true;
}
//+------------------------------------------------------------------+
#endif // WARRIOR_ATOMIC_FILE_MQH