// AtomicWrite.cpp : Defines the entry point for the console application.
//

#include <stdio.h>
#include <tchar.h>
#include <Windows.h>
#include <atlfile.h>

DWORD WINAPI WriteThreads(LPVOID name)
{
    while(1)
    {
        CAtlFile file;
        file.Create((LPCTSTR) name, GENERIC_WRITE, 0, CREATE_ALWAYS);

        for(int i =0; i < 10000; i++)
        {
            char buf[1024];
            memset(buf, 0x11, sizeof(buf));
            file.Write(buf, sizeof(buf));
        }
        file.Flush();
        file.Close();
        Sleep(1);
    }
}

void Verify(LPCWSTR name)
{
    CAtlFile file;
    if (file.Create((LPCTSTR) name, GENERIC_READ, 0, OPEN_EXISTING) == S_OK)
    {
        char buf[100];
        DWORD read;
        file.Read(buf, sizeof(buf), read);

        if (read != 10)
        {
            wprintf(L"Invalid len %s\n", name);
            exit(1);
        }
        for(int i = 0; i < read; i++)
        {
            if (buf[i] != i)
            {
                wprintf(L"Invalid data %s\n", name);
                exit(1);
            }
        }

        file.Close();
    }
}

DWORD WINAPI MoveThread(LPVOID name)
{
    while(1)
    {
        CAtlFile file;
        file.Create(L"tmp", GENERIC_WRITE, 0, CREATE_ALWAYS);

            char buf[10];
        for(int i =0; i < sizeof(buf); i++)
        {
            buf[i] = i;
        }
        file.Write(buf, sizeof(buf));
        // Uncomment to fix issue.
        // file.Flush();
        file.Close();
        if (!MoveFileEx(L"tmp", L"current", MOVEFILE_REPLACE_EXISTING | MOVEFILE_COPY_ALLOWED))
        {

            wprintf(L"move failed: %d\n", GetLastError());
            exit(1);
        }
        Sleep(10);
    }
}



int _tmain(int argc, _TCHAR* argv[])
{
    Verify(L"current");

    CreateThread(NULL, 0, WriteThreads, L"file1", 0, NULL);
    CreateThread(NULL, 0, WriteThreads, L"file2", 0, NULL);
    CreateThread(NULL, 0, WriteThreads, L"file3", 0, NULL);
    CreateThread(NULL, 0, WriteThreads, L"file4", 0, NULL);


    CreateThread(NULL, 0, MoveThread, L"current", 0, NULL);

    
    getc(stdin);
    return 0;
}

