Add ReaderWriterQueue and update ConcurrentQueue

This commit is contained in:
Paul Hollinsky
2020-03-09 13:38:14 -04:00
parent 9ac3fd56bd
commit 42780dc610
1629 changed files with 306008 additions and 868 deletions
@@ -0,0 +1,195 @@
#include "stdafx.h"
#include "../../relacy/relacy_cli.hpp"
using rl::nvar;
using rl::nvolatile;
using rl::mutex;
template<typename T>
class ws_deque
{
public:
ws_deque()
{
m_mask($) = initial_size - 1;
m_headIndex($) = 0;
m_tailIndex($) = 0;
m_array($) = new nvar<T> [initial_size];
m_arraySize($) = initial_size;
}
bool IsEmpty()
{
return m_headIndex($) >= m_tailIndex($);
}
size_t Count()
{
return m_tailIndex($) - m_headIndex($);
}
void push(T item)
{
size_t tail = m_tailIndex($);
if (tail <= m_headIndex($) + m_mask($))
{
m_array($)[tail & m_mask($)]($) = item;
m_tailIndex($) = tail + 1;
}
else
{
m_foreignLock.lock($);
size_t head = m_headIndex($);
size_t count = Count();
if (count >= m_mask($))
{
size_t arraySize = m_arraySize($);
size_t mask = m_mask($);
nvar<T>* newArray = new nvar<T> [arraySize * 2];
nvar<T>* arr = m_array($);
for (size_t i = 0; i != count; ++i)
newArray[i]($) = arr[(i + head) & mask]($);
m_array($) = newArray;
m_arraySize($) = arraySize * 2;
m_headIndex($) = 0;
m_tailIndex($) = count;
tail = count;
m_mask($) = (mask * 2) | 1;
}
m_array($)[tail & m_mask($)]($) = item;
m_tailIndex($) = tail + 1;
m_foreignLock.unlock($);
}
}
bool pop(T& item)
{
size_t tail = m_tailIndex($);
if (tail == 0)
return false;
tail -= 1;
rl::Interlocked::Exchange(m_tailIndex, tail, $);
if (m_headIndex($) <= tail)
{
item = m_array($)[tail & m_mask($)]($);
return true;
}
else
{
m_foreignLock.lock($);
if (m_headIndex($) <= tail)
{
item = m_array($)[tail & m_mask($)]($);
m_foreignLock.unlock($);
return true;
}
else
{
m_tailIndex($) = tail + 1;
m_foreignLock.unlock($);
return false;
}
}
}
bool steal(T& item)
{
if (false == m_foreignLock.try_lock($))
return false;
size_t head = m_headIndex($);
rl::Interlocked::Exchange(m_headIndex, head + 1, $);
if (head < m_tailIndex($))
{
item = m_array($)[head & m_mask($)]($);
m_foreignLock.unlock($);
return true;
}
else
{
m_headIndex($) = head;
m_foreignLock.unlock($);
return false;
}
}
private:
static size_t const initial_size = 2;
nvar<nvar<T>*> m_array;
nvar<size_t> m_mask;
nvar<size_t> m_arraySize;
nvolatile<size_t> m_headIndex;
nvolatile<size_t> m_tailIndex;
mutex m_foreignLock;
};
struct ws_deque_test : rl::test_suite<ws_deque_test, 2>
{
ws_deque<int> q;
bool state [2];
void before()
{
state[0] = true;
state[1] = true;
}
void after()
{
RL_ASSERT(state[0] == false);
RL_ASSERT(state[1] == false);
}
void thread(unsigned index)
{
if (0 == index)
{
q.push(1);
q.push(2);
int item = 0;
bool res = q.pop(item);
RL_ASSERT(res && item == 2);
RL_ASSERT(state[1]);
state[1] = false;
item = 0;
res = q.pop(item);
if (res)
{
RL_ASSERT(state[0]);
state[0] = false;
}
item = 0;
res = q.pop(item);
RL_ASSERT(res == false);
}
else
{
int item = 0;
bool res = q.steal(item);
if (res)
{
RL_ASSERT(item == 1);
RL_ASSERT(state[0]);
state[0] = false;
}
}
}
};
int main()
{
rl::simulate<ws_deque_test>();
}
@@ -0,0 +1,20 @@
Microsoft Visual Studio Solution File, Format Version 9.00
# Visual Studio 2005
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "cli_ws_deque", "cli_ws_deque.vcproj", "{0B597F19-DEBB-4832-B520-9A93A286D595}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Win32 = Debug|Win32
Release|Win32 = Release|Win32
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{0B597F19-DEBB-4832-B520-9A93A286D595}.Debug|Win32.ActiveCfg = Debug|Win32
{0B597F19-DEBB-4832-B520-9A93A286D595}.Debug|Win32.Build.0 = Debug|Win32
{0B597F19-DEBB-4832-B520-9A93A286D595}.Release|Win32.ActiveCfg = Release|Win32
{0B597F19-DEBB-4832-B520-9A93A286D595}.Release|Win32.Build.0 = Release|Win32
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
EndGlobal
@@ -0,0 +1,205 @@
<?xml version="1.0" encoding="windows-1251"?>
<VisualStudioProject
ProjectType="Visual C++"
Version="8,00"
Name="cli_ws_deque"
ProjectGUID="{967F376B-BDBF-4AC8-9325-371CC8ABD8FD}"
RootNamespace="cli_ws_deque"
Keyword="Win32Proj"
>
<Platforms>
<Platform
Name="Win32"
/>
</Platforms>
<ToolFiles>
</ToolFiles>
<Configurations>
<Configuration
Name="Debug|Win32"
OutputDirectory="$(SolutionDir)$(ConfigurationName)"
IntermediateDirectory="$(ConfigurationName)"
ConfigurationType="1"
CharacterSet="1"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
/>
<Tool
Name="VCCLCompilerTool"
Optimization="0"
PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE"
MinimalRebuild="true"
BasicRuntimeChecks="3"
RuntimeLibrary="3"
UsePrecompiledHeader="2"
WarningLevel="4"
DebugInformationFormat="4"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
LinkIncremental="2"
GenerateDebugInformation="true"
SubSystem="1"
TargetMachine="1"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCWebDeploymentTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
<Configuration
Name="Release|Win32"
OutputDirectory="$(SolutionDir)$(ConfigurationName)"
IntermediateDirectory="$(ConfigurationName)"
ConfigurationType="1"
CharacterSet="1"
WholeProgramOptimization="1"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
/>
<Tool
Name="VCCLCompilerTool"
PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE"
RuntimeLibrary="2"
UsePrecompiledHeader="2"
WarningLevel="4"
DebugInformationFormat="3"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
LinkIncremental="1"
GenerateDebugInformation="true"
SubSystem="1"
OptimizeReferences="2"
EnableCOMDATFolding="2"
TargetMachine="1"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCWebDeploymentTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
</Configurations>
<References>
</References>
<Files>
<File
RelativePath="..\cli_ws_deque.cpp"
>
</File>
<File
RelativePath="..\stdafx.cpp"
>
<FileConfiguration
Name="Debug|Win32"
>
<Tool
Name="VCCLCompilerTool"
UsePrecompiledHeader="1"
ObjectFile="$(IntDir)\$(InputName)1.obj"
XMLDocumentationFileName="$(IntDir)\$(InputName)1.xdc"
/>
</FileConfiguration>
<FileConfiguration
Name="Release|Win32"
>
<Tool
Name="VCCLCompilerTool"
UsePrecompiledHeader="1"
ObjectFile="$(IntDir)\$(InputName)1.obj"
XMLDocumentationFileName="$(IntDir)\$(InputName)1.xdc"
/>
</FileConfiguration>
</File>
<File
RelativePath="..\stdafx.h"
>
</File>
</Files>
<Globals>
</Globals>
</VisualStudioProject>
@@ -0,0 +1,2 @@
#include "stdafx.h"
@@ -0,0 +1,7 @@
#pragma once
#include "../../relacy/pch.hpp"
@@ -0,0 +1,181 @@
#include "stdafx.h"
#include "../../relacy/relacy_std.hpp"
// THE TEST IS EXPECTED TO FAIL WITH "DEADLOCK"
class CondVar
{
public:
CondVar();
~CondVar();
void Enter();
void Wait();
void Release();
void ReleaseAll();
void Leave();
private:
std::atomic<int> m_lMutex;
std::atomic<unsigned> m_dwWaitingForSignal;
HANDLE m_xhEvtEnter;
HANDLE m_xhSemRelease;
};
CondVar::CondVar()
: m_xhEvtEnter(CreateEvent(0, 0, 0, 0))
, m_xhSemRelease(CreateSemaphore(0, 0, 0x7FFFFFFF, 0))
{
m_lMutex.store(0, std::memory_order_relaxed);
m_dwWaitingForSignal.store(0, std::memory_order_relaxed);
}
CondVar::~CondVar()
{
CloseHandle(m_xhEvtEnter);
CloseHandle(m_xhSemRelease);
}
void CondVar::Enter()
{
int lMutex = m_lMutex.load(std::memory_order_seq_cst);
for (;;)
{
if( lMutex >= 0 )
{
if (m_lMutex.compare_exchange_weak(lMutex, lMutex | 0x80000000u, std::memory_order_seq_cst))
break;
}
else
{
if (false == m_lMutex.compare_exchange_weak(lMutex, lMutex + 1, std::memory_order_seq_cst))
continue;
WaitForSingleObject(m_xhEvtEnter, INFINITE);
RL_ASSERT(m_lMutex.load(std::memory_order_seq_cst) < 0);
break;
}
}
}
void CondVar::Wait()
{
unsigned dwWaitingForSignal = m_dwWaitingForSignal.load(std::memory_order_seq_cst);
m_dwWaitingForSignal.store(dwWaitingForSignal + 1, std::memory_order_seq_cst);
RL_ASSERT(m_lMutex.load(std::memory_order_seq_cst) < 0);
int lMutex = m_lMutex.load(std::memory_order_seq_cst);
for (;;)
{
unsigned dwWaitingToOwn = lMutex & 0x7FFFFFFFu;
RL_ASSERT(dwWaitingToOwn >= dwWaitingForSignal);
if (dwWaitingToOwn == dwWaitingForSignal)
{
if (m_lMutex.compare_exchange_weak(lMutex, dwWaitingToOwn + 1, std::memory_order_seq_cst))
break;
}
else
{
SetEvent(m_xhEvtEnter);
break;
}
}
WaitForSingleObject(m_xhSemRelease, INFINITE);
WaitForSingleObject(m_xhEvtEnter, INFINITE);
RL_ASSERT(m_lMutex.load(std::memory_order_seq_cst) < 0);
}
void CondVar::Release()
{
RL_ASSERT(m_lMutex.load(std::memory_order_seq_cst) < 0);
unsigned dwWaitingForSignal = m_dwWaitingForSignal.load(std::memory_order_seq_cst);
if (dwWaitingForSignal != 0)
{
m_dwWaitingForSignal.store(dwWaitingForSignal - 1, std::memory_order_seq_cst);
ReleaseSemaphore(m_xhSemRelease, 1, 0);
}
}
void CondVar::ReleaseAll()
{
RL_ASSERT(m_lMutex.load(std::memory_order_seq_cst) < 0);
unsigned dwWaitingForSignal = m_dwWaitingForSignal.load(std::memory_order_seq_cst);
if (dwWaitingForSignal != 0)
{
m_dwWaitingForSignal.store(0, std::memory_order_seq_cst);
ReleaseSemaphore(m_xhSemRelease, dwWaitingForSignal, 0);
}
}
void CondVar::Leave()
{
int lMutex = m_lMutex.load(std::memory_order_seq_cst);
RL_ASSERT(lMutex < 0);
for (;;)
{
unsigned dwWaitingToOwn = lMutex & 0x7FFFFFFFu;
unsigned dwWaitingForSignal = m_dwWaitingForSignal.load(std::memory_order_seq_cst);
RL_ASSERT(dwWaitingToOwn >= dwWaitingForSignal);
if (dwWaitingToOwn == dwWaitingForSignal)
{
if (m_lMutex.compare_exchange_weak(lMutex, lMutex & 0x7FFFFFFF, std::memory_order_seq_cst))
break;
}
else
{
if (false == m_lMutex.compare_exchange_weak(lMutex, lMutex - 1, std::memory_order_seq_cst))
continue;
SetEvent(m_xhEvtEnter);
break;
}
}
}
struct CondVarTest : rl::test_suite<CondVarTest, 3>
{
VAR_T(int) stage;
CondVar cv;
void before()
{
VAR(stage) = 0;
}
void thread(unsigned index)
{
if (0 == index)
{
cv.Enter();
VAR(stage) += 1;
cv.ReleaseAll();
while (VAR(stage) != 2)
cv.Wait();
cv.Leave();
}
else if (1 == index)
{
cv.Enter();
while (VAR(stage) != 1)
cv.Wait();
VAR(stage) += 1;
cv.ReleaseAll();
cv.Leave();
}
else if (2 == index)
{
cv.Enter();
while (VAR(stage) != 2)
cv.Wait();
cv.Leave();
}
}
};
int main()
{
rl::simulate<CondVarTest>();
}
@@ -0,0 +1,20 @@
Microsoft Visual Studio Solution File, Format Version 9.00
# Visual Studio 2005
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "condvar", "condvar.vcproj", "{D4756EE9-3953-4E17-B1B5-E89F853303C1}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Win32 = Debug|Win32
Release|Win32 = Release|Win32
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{D4756EE9-3953-4E17-B1B5-E89F853303C1}.Debug|Win32.ActiveCfg = Debug|Win32
{D4756EE9-3953-4E17-B1B5-E89F853303C1}.Debug|Win32.Build.0 = Debug|Win32
{D4756EE9-3953-4E17-B1B5-E89F853303C1}.Release|Win32.ActiveCfg = Release|Win32
{D4756EE9-3953-4E17-B1B5-E89F853303C1}.Release|Win32.Build.0 = Release|Win32
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
EndGlobal
@@ -0,0 +1,205 @@
<?xml version="1.0" encoding="windows-1251"?>
<VisualStudioProject
ProjectType="Visual C++"
Version="8,00"
Name="condvar"
ProjectGUID="{6CC59CF8-408B-441B-8F65-15651210CB82}"
RootNamespace="condvar"
Keyword="Win32Proj"
>
<Platforms>
<Platform
Name="Win32"
/>
</Platforms>
<ToolFiles>
</ToolFiles>
<Configurations>
<Configuration
Name="Debug|Win32"
OutputDirectory="$(SolutionDir)$(ConfigurationName)"
IntermediateDirectory="$(ConfigurationName)"
ConfigurationType="1"
CharacterSet="1"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
/>
<Tool
Name="VCCLCompilerTool"
Optimization="0"
PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE"
MinimalRebuild="true"
BasicRuntimeChecks="3"
RuntimeLibrary="3"
UsePrecompiledHeader="2"
WarningLevel="4"
DebugInformationFormat="4"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
LinkIncremental="2"
GenerateDebugInformation="true"
SubSystem="1"
TargetMachine="1"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCWebDeploymentTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
<Configuration
Name="Release|Win32"
OutputDirectory="$(SolutionDir)$(ConfigurationName)"
IntermediateDirectory="$(ConfigurationName)"
ConfigurationType="1"
CharacterSet="1"
WholeProgramOptimization="1"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
/>
<Tool
Name="VCCLCompilerTool"
PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE"
RuntimeLibrary="2"
UsePrecompiledHeader="2"
WarningLevel="4"
DebugInformationFormat="3"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
LinkIncremental="1"
GenerateDebugInformation="true"
SubSystem="1"
OptimizeReferences="2"
EnableCOMDATFolding="2"
TargetMachine="1"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCWebDeploymentTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
</Configurations>
<References>
</References>
<Files>
<File
RelativePath="..\condvar.cpp"
>
</File>
<File
RelativePath="..\stdafx.cpp"
>
<FileConfiguration
Name="Debug|Win32"
>
<Tool
Name="VCCLCompilerTool"
UsePrecompiledHeader="1"
ObjectFile="$(IntDir)\$(InputName)1.obj"
XMLDocumentationFileName="$(IntDir)\$(InputName)1.xdc"
/>
</FileConfiguration>
<FileConfiguration
Name="Release|Win32"
>
<Tool
Name="VCCLCompilerTool"
UsePrecompiledHeader="1"
ObjectFile="$(IntDir)\$(InputName)1.obj"
XMLDocumentationFileName="$(IntDir)\$(InputName)1.xdc"
/>
</FileConfiguration>
</File>
<File
RelativePath="..\stdafx.h"
>
</File>
</Files>
<Globals>
</Globals>
</VisualStudioProject>
@@ -0,0 +1,20 @@
Microsoft Visual Studio Solution File, Format Version 10.00
# Visual Studio 2008
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "condvar", "condvar.vcproj", "{D4756EE9-3953-4E17-B1B5-E89F853303C1}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Win32 = Debug|Win32
Release|Win32 = Release|Win32
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{D4756EE9-3953-4E17-B1B5-E89F853303C1}.Debug|Win32.ActiveCfg = Debug|Win32
{D4756EE9-3953-4E17-B1B5-E89F853303C1}.Debug|Win32.Build.0 = Debug|Win32
{D4756EE9-3953-4E17-B1B5-E89F853303C1}.Release|Win32.ActiveCfg = Release|Win32
{D4756EE9-3953-4E17-B1B5-E89F853303C1}.Release|Win32.Build.0 = Release|Win32
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
EndGlobal
@@ -0,0 +1,205 @@
<?xml version="1.0" encoding="windows-1251"?>
<VisualStudioProject
ProjectType="Visual C++"
Version="9,00"
Name="condvar"
ProjectGUID="{6CC59CF8-408B-441B-8F65-15651210CB82}"
RootNamespace="condvar"
Keyword="Win32Proj"
>
<Platforms>
<Platform
Name="Win32"
/>
</Platforms>
<ToolFiles>
</ToolFiles>
<Configurations>
<Configuration
Name="Debug|Win32"
OutputDirectory="$(SolutionDir)$(ConfigurationName)"
IntermediateDirectory="$(ConfigurationName)"
ConfigurationType="1"
CharacterSet="1"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
/>
<Tool
Name="VCCLCompilerTool"
Optimization="0"
PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE"
MinimalRebuild="true"
BasicRuntimeChecks="3"
RuntimeLibrary="3"
UsePrecompiledHeader="2"
WarningLevel="4"
DebugInformationFormat="4"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
LinkIncremental="2"
GenerateDebugInformation="true"
SubSystem="1"
TargetMachine="1"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCWebDeploymentTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
<Configuration
Name="Release|Win32"
OutputDirectory="$(SolutionDir)$(ConfigurationName)"
IntermediateDirectory="$(ConfigurationName)"
ConfigurationType="1"
CharacterSet="1"
WholeProgramOptimization="1"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
/>
<Tool
Name="VCCLCompilerTool"
PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE"
RuntimeLibrary="2"
UsePrecompiledHeader="2"
WarningLevel="4"
DebugInformationFormat="3"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
LinkIncremental="1"
GenerateDebugInformation="true"
SubSystem="1"
OptimizeReferences="2"
EnableCOMDATFolding="2"
TargetMachine="1"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCWebDeploymentTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
</Configurations>
<References>
</References>
<Files>
<File
RelativePath="..\condvar.cpp"
>
</File>
<File
RelativePath="..\stdafx.cpp"
>
<FileConfiguration
Name="Debug|Win32"
>
<Tool
Name="VCCLCompilerTool"
UsePrecompiledHeader="1"
ObjectFile="$(IntDir)\$(InputName)1.obj"
XMLDocumentationFileName="$(IntDir)\$(InputName)1.xdc"
/>
</FileConfiguration>
<FileConfiguration
Name="Release|Win32"
>
<Tool
Name="VCCLCompilerTool"
UsePrecompiledHeader="1"
ObjectFile="$(IntDir)\$(InputName)1.obj"
XMLDocumentationFileName="$(IntDir)\$(InputName)1.xdc"
/>
</FileConfiguration>
</File>
<File
RelativePath="..\stdafx.h"
>
</File>
</Files>
<Globals>
</Globals>
</VisualStudioProject>
@@ -0,0 +1,2 @@
#include "stdafx.h"
@@ -0,0 +1,14 @@
#pragma once
#ifdef NDEBUG
# define _SECURE_SCL 0
#endif
#define RL_MSVC_OUTPUT
//#define RL_DEBUGBREAK_ON_FAILURE
#include "../../relacy/pch.hpp"
#include "../../relacy/relacy_std.hpp"
@@ -0,0 +1,178 @@
/*
#define BOOST_ALL_NO_LIB
#pragma warning (push, 3)
#include <boost/thread/mutex.hpp>
#include <boost/thread/shared_mutex.hpp>
#include "C:\boost_1_35_0\libs\thread\src\win32\exceptions.cpp"
#pragma warning (pop)
class business_logic
{
public:
typedef unsigned account_id_t;
typedef double balance_t;
bool add_account(account_id_t acc_id, balance_t balance)
{
accounts_guard.lock();
if (accounts.find(acc_id) != accounts.end())
{
accounts_guard.unlock();
return false;
}
accounts[acc_id].balance = balance;
accounts_guard.unlock();
return true;
}
bool transfer_balance(account_id_t acc_id1, account_id_t acc_id2, balance_t amount)
{
accounts_guard.lock_shared();
if (accounts.find(acc_id1) != accounts.end()
|| accounts.find(acc_id2) != accounts.end())
{
accounts_guard.unlock_shared();
return false;
}
account_info& acc1 = accounts[acc_id1];
account_info& acc2 = accounts[acc_id2];
acc1.mtx.lock();
acc2.mtx.lock();
accounts_guard.unlock_shared();
acc1.balance -= amount;
acc2.balance += amount;
acc1.mtx.unlock();
acc2.mtx.unlock();
return true;
}
private:
struct account_info
{
balance_t balance;
boost::mutex mtx;
account_info()
: balance()
{}
account_info(account_info const& acc)
: balance(acc.balance)
{}
};
typedef std::map<account_id_t, account_info> account_map_t;
account_map_t accounts;
boost::shared_mutex accounts_guard;
};
*/
/*
#undef RL_TEST
#ifndef RL_TEST
//# define ASSERT assert
typedef boost::mutex mutex_t;
# define $$
#else
//# define ASSERT RL_ASSERT
typedef rl::recursive_mutex mutex_t;
# define $$ $
#endif
class business_logic
{
public:
typedef unsigned account_id_t;
typedef double balance_t;
bool add_account(account_id_t acc_id, balance_t balance)
{
accounts_guard.lock($$);
if (accounts.find(acc_id) != accounts.end())
{
accounts_guard.unlock($$);
return false;
}
accounts[acc_id].balance = balance;
accounts_guard.unlock($$);
return true;
}
bool transfer_balance(account_id_t acc_id1, account_id_t acc_id2, balance_t amount)
{
accounts_guard.lock($$);
if (accounts.find(acc_id1) == accounts.end()
|| accounts.find(acc_id2) == accounts.end())
{
accounts_guard.unlock($$);
return false;
}
account_info& acc1 = accounts[acc_id1];
account_info& acc2 = accounts[acc_id2];
acc1.mtx.lock($$);
acc2.mtx.lock($$);
accounts_guard.unlock($$);
acc1.balance -= amount;
acc2.balance += amount;
acc1.mtx.unlock($$);
acc2.mtx.unlock($$);
return true;
}
private:
struct account_info
{
balance_t balance;
mutex_t mtx;
account_info()
: balance()
{}
account_info(account_info const& acc)
: balance(acc.balance)
{}
};
typedef std::map<account_id_t, account_info> account_map_t;
account_map_t accounts;
mutex_t accounts_guard;
};
*/
/*
struct business_logic_test : rl::test_suite<business_logic_test, 2>
{
business_logic bl;
static size_t const account_count = 10;
void before()
{
for (size_t i = 0; i != account_count; ++i)
{
bool rv = bl.add_account(i, i * 10.0);
RL_ASSERT(rv);
}
}
void thread(unsigned)
{
business_logic::account_id_t acc1 = rl::rand(account_count);
business_logic::account_id_t acc2 = rl::rand(account_count);
bool rv = bl.transfer_balance(acc1, acc2, 1.0);
RL_ASSERT(rv);
}
};
*/
@@ -0,0 +1,707 @@
#include "stdafx.h"
#include "../../relacy/windows.h"
#define HANDLE rl::HANDLE
#define CreateSemaphoreA rl::RL_CreateSemaphore($)
#define CreateSemaphoreW rl::RL_CreateSemaphore($)
#ifndef CreateSemaphore
# define CreateSemaphore CreateSemaphoreW
#endif
#define CloseHandle rl::RL_CloseHandle($)
#include <stddef.h>
#if defined(WIN32) && defined(_MSC_VER)
#include <windows.h>
#include <intrin.h>
class semaphore
{
public:
semaphore()
{
h_ = CreateSemaphore(0, 0, LONG_MAX, 0);
}
~semaphore()
{
CloseHandle(h_);
}
void wait()
{
WaitForSingleObject(h_, INFINITE);
}
void post()
{
ReleaseSemaphore(h_, 1, 0);
}
private:
HANDLE h_;
semaphore(semaphore const&);
semaphore& operator = (semaphore const&);
};
class mutex
{
public:
mutex()
{
InitializeCriticalSection(&cs_);
}
~mutex()
{
DeleteCriticalSection(&cs_);
}
void lock()
{
EnterCriticalSection(&cs_);
}
void unlock()
{
LeaveCriticalSection(&cs_);
}
private:
CRITICAL_SECTION cs_;
mutex(mutex const&);
mutex& operator = (mutex const&);
};
void full_memory_fence()
{
_mm_mfence();
}
#define THREAD_LOCAL __declspec(thread)
#elif defined(POSIX) && defined(GCC)
#include <pthread.h>
#include <semaphore.h>
class semaphore
{
public:
semaphore()
{
sem_init(&sem_, 0, 0);
}
~semaphore()
{
sem_destroy(&sem_);
}
void wait()
{
sem_wait(&sem_);
}
void post()
{
sem_post(&sem_);
}
private:
sem_t sem_;
semaphore(semaphore const&);
semaphore& operator = (semaphore const&);
};
class mutex
{
public:
mutex()
{
pthread_mutex_init(&mutex_, 0);
}
~mutex()
{
pthread_mutex_destroy(&mutex_);
}
void lock()
{
pthread_mutex_lock(&mutex_);
}
void unlock()
{
pthread_mutex_unlock(&mutex_);
}
private:
pthread_mutex_t mutex_;
mutex(mutex const&);
mutex& operator = (mutex const&);
};
void full_memory_fence()
{
__sync_synchronize();
}
#define THREAD_LOCAL __thread
#endif
class lock
{
public:
lock(mutex& m)
: m_(m)
{
m.lock();
}
~lock()
{
m_.unlock();
}
private:
mutex& m_;
lock(lock const&);
lock& operator = (lock const&);
};
/** simple single-threaded double-linked list
* nothing interesting
*/
class dlist
{
public:
struct node
{
node* prev_;
node* next_;
node()
{
prev_ = 0;
next_ = 0;
}
};
dlist()
{
reset();
}
void push(node* n)
{
size_ += 1;
n->next_ = head_.next_;
n->prev_ = &head_;
head_.next_->prev_ = n;
head_.next_ = n;
}
node* pop()
{
if (size_ == 0)
return 0;
node* n = head_.next_;
remove(n);
return n;
}
void remove(node* n)
{
size_ -= 1;
n->prev_->next_ = n->next_;
n->next_->prev_ = n->prev_;
}
size_t size() const
{
return size_;
}
node* begin()
{
return head_.next_;
}
void flush_to(dlist& target)
{
if (size_)
{
target.size_ = size_;
target.head_.next_ = head_.next_;
target.head_.next_->prev_ = &target.head_;
target.tail_.prev_ = tail_.prev_;
target.tail_.prev_->next_ = &target.tail_;
}
else
{
target.reset();
}
reset();
}
static bool not_last(node* n)
{
return n->next_ != 0;
}
static node* get_next(node* n)
{
return n->next_;
}
private:
size_t volatile size_;
node head_;
node tail_;
void reset()
{
size_ = 0;
head_.next_ = &tail_;
head_.prev_ = 0;
tail_.next_ = 0;
tail_.prev_ = &head_;
}
dlist(dlist const&);
dlist& operator = (dlist const&);
};
/** pre-thread descriptor for eventcount
*/
struct ec_thread
{
dlist::node node_;
semaphore sema_;
unsigned epoch_;
bool volatile in_waitset_;
bool spurious_;
void* ctx_;
ec_thread()
{
epoch_ = 0;
in_waitset_ = false;
spurious_ = false;
ctx_ = 0;
}
~ec_thread()
{
if (spurious_)
sema_.wait();
}
static ec_thread* current()
{
static THREAD_LOCAL ec_thread* ec_thread_instance = 0;
ec_thread* instance = ec_thread_instance;
if (instance == 0)
{
instance = new ec_thread;
ec_thread_instance = instance;
}
return instance;
// instance must be destroyed in DllMain() callback
// or in pthread_key_create() callback
}
private:
ec_thread(ec_thread const&);
ec_thread& operator = (ec_thread const&);
};
/** fine-grained eventcount implementation
*/
class eventcount
{
public:
eventcount()
{
epoch_ = 0;
}
void prepare_wait(void* ctx = 0)
{
ec_thread* th = ec_thread::current();
// this is good place to pump previous spurious wakeup
if (th->spurious_)
{
th->spurious_ = false;
th->sema_.wait();
}
th->in_waitset_ = true;
th->ctx_ = ctx;
{
lock l (mtx_);
th->epoch_ = epoch_;
waitset_.push(&th->node_);
}
full_memory_fence();
}
void wait()
{
ec_thread* th = ec_thread::current();
// this check is just an optimization
if (th->epoch_ == epoch_)
th->sema_.wait();
else
retire_wait();
}
void retire_wait()
{
ec_thread* th = ec_thread::current();
// spurious wakeup will be pumped in following prepare_wait()
th->spurious_ = true;
// try to remove node from waitset
if (th->in_waitset_)
{
lock l (mtx_);
if (th->in_waitset_)
{
// successfully removed from waitset,
// so there will be no spurious wakeup
th->in_waitset_ = false;
th->spurious_ = false;
waitset_.remove(&th->node_);
}
}
}
void notify_one()
{
full_memory_fence();
notify_one_relaxed();
}
template<typename predicate_t>
void notify(predicate_t pred)
{
full_memory_fence();
notify_relaxed(pred);
}
void notify_all()
{
full_memory_fence();
notify_all_relaxed();
}
void notify_one_relaxed()
{
if (waitset_.size() == 0)
return;
dlist::node* n;
{
lock l (mtx_);
epoch_ += 1;
n = waitset_.pop();
if (n)
to_ec_thread(n)->in_waitset_ = false;
}
if (n)
{
to_ec_thread(n)->sema_.post();
}
}
template<typename predicate_t>
void notify_relaxed(predicate_t pred)
{
if (waitset_.size() == 0)
return;
dlist temp;
{
lock l (mtx_);
epoch_ += 1;
size_t size = waitset_.size();
size_t idx = 0;
dlist::node* n = waitset_.begin();
while (dlist::not_last(n))
{
dlist::node* next = dlist::get_next(n);
ec_thread* th = to_ec_thread(n);
if (pred(th->ctx_, size, idx))
{
waitset_.remove(n);
temp.push(n);
th->in_waitset_ = false;
}
n = next;
idx += 1;
}
}
dlist::node* n = temp.begin();
while (dlist::not_last(n))
{
dlist::node* next = dlist::get_next(n);
to_ec_thread(n)->sema_.post();
n = next;
}
}
void notify_all_relaxed()
{
if (waitset_.size() == 0)
return;
dlist temp;
{
lock l (mtx_);
epoch_ += 1;
waitset_.flush_to(temp);
dlist::node* n = temp.begin();
while (dlist::not_last(n))
{
to_ec_thread(n)->in_waitset_ = false;
n = dlist::get_next(n);
}
}
dlist::node* n = temp.begin();
while (dlist::not_last(n))
{
dlist::node* next = dlist::get_next(n);
to_ec_thread(n)->sema_.post();
n = next;
}
}
private:
mutex mtx_;
dlist waitset_;
volatile unsigned epoch_;
ec_thread* to_ec_thread(dlist::node* n)
{
return (ec_thread*)((char*)n - offsetof(ec_thread, node_));
}
eventcount(eventcount const&);
eventcount& operator = (eventcount const&);
};
struct scheduler
{
struct tbb_thread {};
eventcount ec_;
tbb_thread* threads_;
bool volatile is_permanently_open_;
void wait_while_pool_is_empty(tbb_thread* th)
{
if (is_permanently_open_)
return;
ec_.prepare_wait(th);
if (pool_is_empty())
ec_.wait();
else
ec_.retire_wait();
}
void notify_about_new_task_available()
{
ec_.notify_one_relaxed();
}
void notify_about_new_task_available_with_preference(tbb_thread* preference)
{
struct local
{
tbb_thread* preference_;
bool fired_;
bool operator () (void* ctx, size_t count, size_t idx)
{
tbb_thread* th = (tbb_thread*)ctx;
if (th == preference_)
{
fired_ = true;
return true;
}
else if (idx == count - 1 && fired_ == false)
{
return true;
}
else
{
return false;
}
}
}
pred = {preference};
ec_.notify_relaxed(pred);
}
void notify_about_list_of_tasks_available(size_t total_count, size_t preference_count, tbb_thread** preferences)
{
struct local
{
size_t remain_to_signal_;
size_t preference_count_;
tbb_thread** preferences_;
bool operator () (void* ctx, size_t count, size_t idx)
{
tbb_thread* th = (tbb_thread*)ctx;
size_t remain_in_waitset = count - idx;
if (remain_in_waitset <= remain_to_signal_)
{
return true;
}
else
{
for (size_t i = 0; i != preference_count_; ++i)
{
if (preferences_[i] == th)
{
remain_to_signal_ -= 1;
return true;
}
}
}
return false;
}
}
pred = {total_count, preference_count, preferences};
ec_.notify_relaxed(pred);
}
bool pool_is_empty()
{
return true;
}
};
struct queue
{
int producer_idx_;
int consumer_idx_;
void** buffer_;
eventcount ec_;
void enqueue(void* data)
{
int idx = ++producer_idx_; // atomic
buffer_[idx] = data;
struct local
{
int idx_;
bool operator () (void* ctx, size_t /*count*/, size_t /*idx*/)
{
return idx_ == *(int*)ctx;
}
}
pred = {idx};
ec_.notify(pred); // not relaxed!!!
}
void* dequeue()
{
int idx = ++consumer_idx_; // atomic
void* data = buffer_[idx];
if (data)
return data;
for (;;)
{
ec_.prepare_wait(&idx);
data = buffer_[idx];
if (data)
{
ec_.retire_wait();
return data;
}
ec_.wait();
data = buffer_[idx];
if (data)
{
return data;
}
}
}
};
class condition_variable
{
eventcount ec_;
public:
void wait(mutex& mtx)
{
ec_.prepare_wait();
mtx.unlock();
ec_.wait();
mtx.lock();
}
void signal()
{
ec_.notify_one();
}
void broadcast()
{
ec_.notify_all();
}
};
struct eventcount_test : rl::test_suite<eventcount_test, 2>
{
void thread(unsigned index)
{
delete ec_thread::current();
(void)index;
}
};
int main()
{
rl::test_params p;
//p.iteration_count = 1000000;
rl::simulate<eventcount_test>(p);
}
@@ -0,0 +1,20 @@
Microsoft Visual Studio Solution File, Format Version 9.00
# Visual Studio 2005
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "eventcount", "eventcount.vcproj", "{ECB64178-A35E-4EB2-9EB0-BD72D6F7B6E5}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Win32 = Debug|Win32
Release|Win32 = Release|Win32
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{ECB64178-A35E-4EB2-9EB0-BD72D6F7B6E5}.Debug|Win32.ActiveCfg = Debug|Win32
{ECB64178-A35E-4EB2-9EB0-BD72D6F7B6E5}.Debug|Win32.Build.0 = Debug|Win32
{ECB64178-A35E-4EB2-9EB0-BD72D6F7B6E5}.Release|Win32.ActiveCfg = Release|Win32
{ECB64178-A35E-4EB2-9EB0-BD72D6F7B6E5}.Release|Win32.Build.0 = Release|Win32
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
EndGlobal
@@ -0,0 +1,203 @@
<?xml version="1.0" encoding="windows-1251"?>
<VisualStudioProject
ProjectType="Visual C++"
Version="8,00"
Name="eventcount"
ProjectGUID="{ECB64178-A35E-4EB2-9EB0-BD72D6F7B6E54}"
RootNamespace="eventcount"
Keyword="Win32Proj"
>
<Platforms>
<Platform
Name="Win32"
/>
</Platforms>
<ToolFiles>
</ToolFiles>
<Configurations>
<Configuration
Name="Debug|Win32"
OutputDirectory="$(SolutionDir)$(ConfigurationName)"
IntermediateDirectory="$(ConfigurationName)"
ConfigurationType="1"
CharacterSet="1"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
/>
<Tool
Name="VCCLCompilerTool"
Optimization="0"
PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE"
MinimalRebuild="true"
BasicRuntimeChecks="3"
RuntimeLibrary="3"
UsePrecompiledHeader="2"
WarningLevel="4"
Detect64BitPortabilityProblems="false"
DebugInformationFormat="4"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
LinkIncremental="2"
GenerateDebugInformation="true"
SubSystem="1"
TargetMachine="1"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCWebDeploymentTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
<Configuration
Name="Release|Win32"
OutputDirectory="$(SolutionDir)$(ConfigurationName)"
IntermediateDirectory="$(ConfigurationName)"
ConfigurationType="1"
CharacterSet="1"
WholeProgramOptimization="1"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
/>
<Tool
Name="VCCLCompilerTool"
PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE"
RuntimeLibrary="2"
UsePrecompiledHeader="2"
WarningLevel="4"
Detect64BitPortabilityProblems="false"
DebugInformationFormat="3"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
LinkIncremental="1"
GenerateDebugInformation="true"
SubSystem="1"
OptimizeReferences="2"
EnableCOMDATFolding="2"
TargetMachine="1"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCWebDeploymentTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
</Configurations>
<References>
</References>
<Files>
<File
RelativePath="..\stdafx.cpp"
>
<FileConfiguration
Name="Debug|Win32"
>
<Tool
Name="VCCLCompilerTool"
UsePrecompiledHeader="1"
/>
</FileConfiguration>
<FileConfiguration
Name="Release|Win32"
>
<Tool
Name="VCCLCompilerTool"
UsePrecompiledHeader="1"
/>
</FileConfiguration>
</File>
<File
RelativePath="..\stdafx.h"
>
</File>
<File
RelativePath="..\eventcount.cpp"
>
</File>
</Files>
<Globals>
</Globals>
</VisualStudioProject>
@@ -0,0 +1,20 @@
Microsoft Visual Studio Solution File, Format Version 10.00
# Visual Studio 2005
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "eventcount", "eventcount.vcproj", "{ECB64178-A35E-4EB2-9EB0-BD72D6F7B6E5}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Win32 = Debug|Win32
Release|Win32 = Release|Win32
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{ECB64178-A35E-4EB2-9EB0-BD72D6F7B6E4}.Debug|Win32.ActiveCfg = Debug|Win32
{ECB64178-A35E-4EB2-9EB0-BD72D6F7B6E4}.Debug|Win32.Build.0 = Debug|Win32
{ECB64178-A35E-4EB2-9EB0-BD72D6F7B6E4}.Release|Win32.ActiveCfg = Release|Win32
{ECB64178-A35E-4EB2-9EB0-BD72D6F7B6E4}.Release|Win32.Build.0 = Release|Win32
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
EndGlobal
@@ -0,0 +1,203 @@
<?xml version="1.0" encoding="windows-1251"?>
<VisualStudioProject
ProjectType="Visual C++"
Version="9,00"
Name="eventcount"
ProjectGUID="{ECB64178-A35E-4EB2-9EB0-BD72D6F7B6E54}"
RootNamespace="eventcount"
Keyword="Win32Proj"
>
<Platforms>
<Platform
Name="Win32"
/>
</Platforms>
<ToolFiles>
</ToolFiles>
<Configurations>
<Configuration
Name="Debug|Win32"
OutputDirectory="$(SolutionDir)$(ConfigurationName)"
IntermediateDirectory="$(ConfigurationName)"
ConfigurationType="1"
CharacterSet="1"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
/>
<Tool
Name="VCCLCompilerTool"
Optimization="0"
PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE"
MinimalRebuild="true"
BasicRuntimeChecks="3"
RuntimeLibrary="3"
UsePrecompiledHeader="2"
WarningLevel="4"
Detect64BitPortabilityProblems="false"
DebugInformationFormat="4"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
LinkIncremental="2"
GenerateDebugInformation="true"
SubSystem="1"
TargetMachine="1"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCWebDeploymentTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
<Configuration
Name="Release|Win32"
OutputDirectory="$(SolutionDir)$(ConfigurationName)"
IntermediateDirectory="$(ConfigurationName)"
ConfigurationType="1"
CharacterSet="1"
WholeProgramOptimization="1"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
/>
<Tool
Name="VCCLCompilerTool"
PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE"
RuntimeLibrary="2"
UsePrecompiledHeader="2"
WarningLevel="4"
Detect64BitPortabilityProblems="false"
DebugInformationFormat="3"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
LinkIncremental="1"
GenerateDebugInformation="true"
SubSystem="1"
OptimizeReferences="2"
EnableCOMDATFolding="2"
TargetMachine="1"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCWebDeploymentTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
</Configurations>
<References>
</References>
<Files>
<File
RelativePath="..\stdafx.cpp"
>
<FileConfiguration
Name="Debug|Win32"
>
<Tool
Name="VCCLCompilerTool"
UsePrecompiledHeader="1"
/>
</FileConfiguration>
<FileConfiguration
Name="Release|Win32"
>
<Tool
Name="VCCLCompilerTool"
UsePrecompiledHeader="1"
/>
</FileConfiguration>
</File>
<File
RelativePath="..\stdafx.h"
>
</File>
<File
RelativePath="..\eventcount.cpp"
>
</File>
</Files>
<Globals>
</Globals>
</VisualStudioProject>
@@ -0,0 +1,8 @@
// stdafx.cpp : source file that includes just the standard includes
// ws_deque.pch will be the pre-compiled header
// stdafx.obj will contain the pre-compiled type information
#include "stdafx.h"
// TODO: reference any additional headers you need in STDAFX.H
// and not in this file
@@ -0,0 +1,10 @@
#pragma once
#define _WIN32_WINNT 0x0500
#include <windows.h>
#include <intrin.h>
#include <stddef.h>
#include "../../relacy/pch.hpp"
#include "../../relacy/relacy_std.hpp"
@@ -0,0 +1,316 @@
#pragma once
struct amp_raw_condition_variable_s
{
CRITICAL_SECTION access_waiting_threads_count_critsec;
HANDLE wake_waiting_threads_mutex;
HANDLE waking_waiting_threads_count_control_sem;
HANDLE finished_waking_waiting_threads_event;
VAR_T(LONG) waiting_thread_count;
VAR_T(BOOL) broadcast_in_progress;
};
struct amp_raw_mutex_s
{
CRITICAL_SECTION critical_section;
BOOL is_locked;
};
typedef amp_raw_condition_variable_s* amp_raw_condition_variable_t;
typedef amp_raw_mutex_s* amp_raw_mutex_t;
int const AMP_SUCCESS = 0;
int amp_raw_mutex_init(amp_raw_mutex_t mutex)
{
InitializeCriticalSectionAndSpinCount(&mutex->critical_section, 1);
mutex->is_locked = FALSE;
return AMP_SUCCESS;
}
int amp_raw_mutex_finalize(amp_raw_mutex_t mutex)
{
assert(NULL != mutex);
int retval = AMP_SUCCESS;
DeleteCriticalSection(&mutex->critical_section);
return retval;
}
int amp_raw_mutex_lock(amp_raw_mutex_t mutex)
{
assert(NULL != mutex);
EnterCriticalSection(&mutex->critical_section);
mutex->is_locked = TRUE;
return AMP_SUCCESS;
}
int amp_raw_mutex_unlock(amp_raw_mutex_t mutex)
{
assert(NULL != mutex);
mutex->is_locked = FALSE;
LeaveCriticalSection(&mutex->critical_section);
return AMP_SUCCESS;
}
int amp_raw_condition_variable_init(amp_raw_condition_variable_t cond)
{
InitializeCriticalSectionAndSpinCount(&cond->access_waiting_threads_count_critsec, 1);
cond->wake_waiting_threads_mutex = CreateMutex(0, 0, 0);
cond->waking_waiting_threads_count_control_sem = CreateSemaphore(NULL, /* No inheritance to child processes */
0, /* Initially no threads can pass */
LONG_MAX, /* Max semaphore count */
NULL); /* Only intra-process semaphore */
cond->finished_waking_waiting_threads_event = CreateEvent(NULL, /* Default security and no inheritance to child processes */
FALSE, /* No manual reset */
0, /* Initially not signaled */
NULL /* Not inter-process available */
);
cond->VAR(waiting_thread_count) = 0l;
cond->VAR(broadcast_in_progress) = FALSE;
return AMP_SUCCESS;
}
int amp_raw_condition_variable_finalize(amp_raw_condition_variable_t cond)
{
DeleteCriticalSection(&cond->access_waiting_threads_count_critsec);
CloseHandle(cond->wake_waiting_threads_mutex);
CloseHandle(cond->waking_waiting_threads_count_control_sem);
CloseHandle(cond->finished_waking_waiting_threads_event);
int ret_error_code = AMP_SUCCESS;
return ret_error_code;
}
int amp_raw_condition_variable_signal(amp_raw_condition_variable_t cond)
{
WaitForSingleObject(cond->wake_waiting_threads_mutex,
INFINITE);
BOOL at_least_one_waiting_thread = (0l != cond->VAR(waiting_thread_count));
if (at_least_one_waiting_thread) {
LONG prev_sem_count = 0;
ReleaseSemaphore(cond->waking_waiting_threads_count_control_sem,
1,
&prev_sem_count /* No interest in the previous sem count. */
);
WaitForSingleObject(cond->finished_waking_waiting_threads_event,
INFINITE);
}
ReleaseMutex(cond->wake_waiting_threads_mutex);
return AMP_SUCCESS;
}
int amp_raw_condition_variable_broadcast(amp_raw_condition_variable_t cond)
{
WaitForSingleObject(cond->wake_waiting_threads_mutex,
INFINITE);
LONG const waiting_thread_count = cond->VAR(waiting_thread_count);
if (0 < waiting_thread_count) {
cond->VAR(broadcast_in_progress) = TRUE;
/* Releasing the sem here and waiting on it should update the memory of
* the waiting threads to see that a broadcast is in progress.
*/
LONG prev_sem_count = 0;
/* Assuming that less threads exist than max possible semaphore count.
* TODO: @todo Decide if to spin here if the assumption doesn't hold
* true in the future?
*/
ReleaseSemaphore(cond->waking_waiting_threads_count_control_sem,
waiting_thread_count,
&prev_sem_count /* No interest in the previous sem count. */
);
WaitForSingleObject(cond->finished_waking_waiting_threads_event,
INFINITE);
cond->VAR(broadcast_in_progress) = FALSE;
}
ReleaseMutex(cond->wake_waiting_threads_mutex);
return AMP_SUCCESS;
}
int amp_raw_condition_variable_wait(amp_raw_condition_variable_t cond,
struct amp_raw_mutex_s *mutex)
{
WaitForSingleObject(cond->wake_waiting_threads_mutex,
INFINITE);
{
++(cond->VAR(waiting_thread_count));
}
amp_raw_mutex_unlock(mutex);
SignalObjectAndWait(cond->wake_waiting_threads_mutex, cond->waking_waiting_threads_count_control_sem, INFINITE, FALSE);
BOOL broadcast_in_progress = FALSE;
LONG count = 0;
EnterCriticalSection(&cond->access_waiting_threads_count_critsec);
{
count = --(cond->VAR(waiting_thread_count));
broadcast_in_progress = cond->VAR(broadcast_in_progress);
}
LeaveCriticalSection(&cond->access_waiting_threads_count_critsec);
BOOL all_waiting_threads_awake = TRUE;
if (TRUE == broadcast_in_progress && count > 0) {
all_waiting_threads_awake = FALSE;
}
if (TRUE == all_waiting_threads_awake) {
SetEvent(cond->finished_waking_waiting_threads_event);
}
amp_raw_mutex_lock(mutex);
return AMP_SUCCESS;
}
struct amp_condvar_test : rl::test_suite<amp_condvar_test, 2>
{
VAR_T(int) data;
amp_raw_mutex_s mtx;
amp_raw_condition_variable_s cv;
void before()
{
VAR(data) = 0;
amp_raw_mutex_init(&mtx);
amp_raw_condition_variable_init(&cv);
}
void after()
{
amp_raw_mutex_finalize(&mtx);
amp_raw_condition_variable_finalize(&cv);
}
void thread(unsigned index)
{
if (0 == index)
{
amp_raw_mutex_lock(&mtx);
data($) += 1;
amp_raw_condition_variable_signal(&cv);
amp_raw_mutex_unlock(&mtx);
}
else
{
amp_raw_mutex_lock(&mtx);
while (0 == data($))
{
amp_raw_condition_variable_wait(&cv, &mtx);
}
amp_raw_mutex_unlock(&mtx);
}
}
};
struct amp_condvar_test2 : rl::test_suite<amp_condvar_test2, 4>
{
VAR_T(int) stage;
amp_raw_mutex_s mtx;
amp_raw_condition_variable_s cv;
void before()
{
VAR(stage) = 0;
amp_raw_mutex_init(&mtx);
amp_raw_condition_variable_init(&cv);
}
void after()
{
amp_raw_mutex_finalize(&mtx);
amp_raw_condition_variable_finalize(&cv);
}
void thread(unsigned index)
{
if (0 == index)
{
amp_raw_mutex_lock(&mtx);
stage($) += 1;
amp_raw_condition_variable_broadcast(&cv);
while (stage($) < 2)
amp_raw_condition_variable_wait(&cv, &mtx);
amp_raw_mutex_unlock(&mtx);
}
else if (1 == index)
{
amp_raw_mutex_lock(&mtx);
while (stage($) != 1)
amp_raw_condition_variable_wait(&cv, &mtx);
stage($) += 1;
amp_raw_condition_variable_broadcast(&cv);
amp_raw_mutex_unlock(&mtx);
}
else if (2 == index)
{
amp_raw_mutex_lock(&mtx);
while (stage($) != 2)
amp_raw_condition_variable_wait(&cv, &mtx);
stage($) += 1;
//amp_raw_condition_variable_broadcast(&cv);
amp_raw_mutex_unlock(&mtx);
amp_raw_condition_variable_signal(&cv);
}
else if (3 == index)
{
amp_raw_mutex_lock(&mtx);
while (stage($) != 3)
amp_raw_condition_variable_wait(&cv, &mtx);
amp_raw_mutex_unlock(&mtx);
}
}
};
@@ -0,0 +1,17 @@
#include "stdafx.h"
#include "spsc_overwrite_queue.hpp"
#include "amp_condvar.hpp"
int main()
{
rl::test_params p;
p.iteration_count = 10000;
//p.search_type = rl::sched_bound;
//p.context_bound = 3;
rl::execute<spsc_overwrite_queue_test, 2>(p);
rl::simulate<amp_condvar_test>(p);
rl::simulate<amp_condvar_test2>(p);
}
@@ -0,0 +1,20 @@
Microsoft Visual Studio Solution File, Format Version 10.00
# Visual Studio 2008
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "examples", "examples.vcproj", "{6CC59CF8-408B-441B-8F65-15651210CB82}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Win32 = Debug|Win32
Release|Win32 = Release|Win32
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{6CC59CF8-408B-441B-8F65-15651210CB82}.Debug|Win32.ActiveCfg = Debug|Win32
{6CC59CF8-408B-441B-8F65-15651210CB82}.Debug|Win32.Build.0 = Debug|Win32
{6CC59CF8-408B-441B-8F65-15651210CB82}.Release|Win32.ActiveCfg = Release|Win32
{6CC59CF8-408B-441B-8F65-15651210CB82}.Release|Win32.Build.0 = Release|Win32
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
EndGlobal
@@ -0,0 +1,208 @@
<?xml version="1.0" encoding="windows-1251"?>
<VisualStudioProject
ProjectType="Visual C++"
Version="9.00"
Name="examples"
ProjectGUID="{1EB73A6F-7F94-4ED4-8EB3-C245E773207A}"
RootNamespace="examples"
Keyword="Win32Proj"
TargetFrameworkVersion="0"
>
<Platforms>
<Platform
Name="Win32"
/>
</Platforms>
<ToolFiles>
</ToolFiles>
<Configurations>
<Configuration
Name="Debug|Win32"
OutputDirectory="$(SolutionDir)$(ConfigurationName)"
IntermediateDirectory="$(ConfigurationName)"
ConfigurationType="1"
CharacterSet="1"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
/>
<Tool
Name="VCCLCompilerTool"
Optimization="0"
PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE"
MinimalRebuild="true"
BasicRuntimeChecks="3"
RuntimeLibrary="3"
UsePrecompiledHeader="2"
WarningLevel="4"
DebugInformationFormat="4"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
LinkIncremental="2"
GenerateDebugInformation="true"
SubSystem="1"
TargetMachine="1"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
<Configuration
Name="Release|Win32"
OutputDirectory="$(SolutionDir)$(ConfigurationName)"
IntermediateDirectory="$(ConfigurationName)"
ConfigurationType="1"
CharacterSet="1"
WholeProgramOptimization="1"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
/>
<Tool
Name="VCCLCompilerTool"
PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE"
RuntimeLibrary="2"
UsePrecompiledHeader="2"
WarningLevel="4"
DebugInformationFormat="3"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
LinkIncremental="1"
GenerateDebugInformation="true"
SubSystem="1"
OptimizeReferences="2"
EnableCOMDATFolding="2"
TargetMachine="1"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
</Configurations>
<References>
</References>
<Files>
<File
RelativePath="..\amp_condvar.hpp"
>
</File>
<File
RelativePath="..\examples.cpp"
>
</File>
<File
RelativePath="..\spsc_overwrite_queue.hpp"
>
</File>
<File
RelativePath="..\stdafx.cpp"
>
<FileConfiguration
Name="Debug|Win32"
>
<Tool
Name="VCCLCompilerTool"
UsePrecompiledHeader="1"
ObjectFile="$(IntDir)\$(InputName)1.obj"
XMLDocumentationFileName="$(IntDir)\$(InputName)1.xdc"
/>
</FileConfiguration>
<FileConfiguration
Name="Release|Win32"
>
<Tool
Name="VCCLCompilerTool"
UsePrecompiledHeader="1"
ObjectFile="$(IntDir)\$(InputName)1.obj"
XMLDocumentationFileName="$(IntDir)\$(InputName)1.xdc"
/>
</FileConfiguration>
</File>
<File
RelativePath="..\stdafx.h"
>
</File>
</Files>
<Globals>
</Globals>
</VisualStudioProject>
@@ -0,0 +1,202 @@
#pragma once
template<typename T>
class queue
{
public:
queue(size_t count)
{
assert(count >= 6);
sema = CreateSemaphore(0, 0, 1, 0);
waiting.store(false, std::memory_order_relaxed);
deq_node = 0;
block = new node [count];
block->next.store(0, std::memory_order_relaxed);
full_tail = block;
full_head.store(block, std::memory_order_relaxed);
free_head = block + 1;
free_tail.store(block + count - 1, std::memory_order_relaxed);
free_tail.load(std::memory_order_relaxed)->next.store(0, std::memory_order_relaxed);
for (size_t i = 1; i != count - 1; i += 1)
block[i].next.store(block + i + 1, std::memory_order_relaxed);
}
~queue()
{
CloseHandle(sema);
delete [] block;
}
VAR_T(T)& enqueue_prepare()
{
return full_tail->data;
}
void enqueue_commit()
{
node* n = get_free_node();
n->next.store(0, std::memory_order_release);
full_tail->next.store(n, std::memory_order_seq_cst);
bool signal = waiting.load(std::memory_order_seq_cst);
full_tail = n;
if (signal)
{
waiting.store(false, std::memory_order_relaxed);
ReleaseSemaphore(sema, 1, 0);
}
}
VAR_T(T)& dequeue_prepare()
{
deq_node = get_full_node();
return deq_node->data;
}
void dequeue_commit()
{
deq_node->next.store(0, std::memory_order_release);
node* prev = free_tail.exchange(deq_node, std::memory_order_acq_rel);
prev->next.store(deq_node, std::memory_order_release);
}
private:
struct node
{
std::atomic<node*> next;
VAR_T(T) data;
};
node* block;
node* full_tail;
node* free_head;
node* deq_node;
char pad [64];
std::atomic<node*> full_head;
std::atomic<node*> free_tail;
std::atomic<bool> waiting;
HANDLE sema;
node* get_free_node()
{
for (;;)
{
node* n = free_head;
node* next = n->next.load(std::memory_order_acquire);
if (next)
{
free_head = next;
return n;
}
n = full_head.load(std::memory_order_acquire);
next = n->next.load(std::memory_order_acquire);
if (next)
{
if (full_head.compare_exchange_strong(n, next, std::memory_order_seq_cst))
{
//node* n2 = free_head;
//node* next2 = n2->next.load(std::memory_order_acquire);
//if (next2)
//{
// n->next.store(0, std::memory_order_release);
// node* prev = free_tail.exchange(n, std::memory_order_acq_rel);
// prev->next.store(n, std::memory_order_release);
// free_head = next2;
// return n2;
//}
//else
{
return n;
}
}
}
}
}
node* get_full_node()
{
node* n = full_head.load(std::memory_order_acquire);
for (;;)
{
node* next = n->next.load(std::memory_order_acquire);
if (next == 0)
{
waiting.store(true, std::memory_order_seq_cst);
n = full_head.load(std::memory_order_seq_cst);
next = n->next.load(std::memory_order_acquire);
if (next)
{
waiting.store(false, std::memory_order_relaxed);
}
else
{
WaitForSingleObject(sema, INFINITE);
n = full_head.load(std::memory_order_acquire);
continue;
}
}
if (full_head.compare_exchange_strong(n, next, std::memory_order_acq_rel))
return n;
}
}
};
unsigned RL_STDCALL consumer_thread(void* ctx)
{
queue<int>* q = (queue<int>*)ctx;
int prev_data = -1;
for (;;)
{
VAR_T(int)& data0 = q->dequeue_prepare();
int data = VAR(data0);
assert(data > prev_data);
prev_data = data;
q->dequeue_commit();
//printf("%d\n", prev_data);
if (prev_data == 11)
break;
//Sleep(5);
}
return 0;
}
unsigned RL_STDCALL producer_thread(void* ctx)
{
queue<int>* q = (queue<int>*)ctx;
for (int i = 0; i != 12; i += 1)
{
VAR_T(int)& data = q->enqueue_prepare();
VAR(data) = i;
q->enqueue_commit();
//Sleep(1);
}
return 0;
}
void spsc_overwrite_queue_test()
{
queue<int> q (6);
HANDLE th [2];
th[0] = (HANDLE)_beginthreadex(0, 0, consumer_thread, &q, 0, 0);
th[1] = (HANDLE)_beginthreadex(0, 0, producer_thread, &q, 0, 0);
WaitForMultipleObjects(2, th, 1, INFINITE);
for (int i = 100; i != 104; i += 1)
{
VAR_T(int)& data = q.enqueue_prepare();
VAR(data) = i;
q.enqueue_commit();
}
for (int i = 100; i != 104; i += 1)
{
VAR_T(int)& data0 = q.dequeue_prepare();
int data = VAR(data0);
assert(data == i);
q.dequeue_commit();
}
}
@@ -0,0 +1,2 @@
#include "stdafx.h"
@@ -0,0 +1,16 @@
#pragma once
#ifdef NDEBUG
# define _SECURE_SCL 0
#endif
#define RL_FORCE_SEQ_CST
#define RL_MSVC_OUTPUT
//#define RL_DEBUGBREAK_ON_FAILURE
#include "../../relacy/pch.hpp"
#include "../../relacy/relacy_std.hpp"
#include "../../relacy/stdlib/windows.hpp"
@@ -0,0 +1,195 @@
#include "stdafx.h"
#include "../../relacy/relacy_java.hpp"
using rl::jvar;
using rl::jvolatile;
using rl::mutex;
template<typename T>
class ws_deque
{
public:
ws_deque()
{
m_mask($) = initial_size - 1;
m_headIndex($) = 0;
m_tailIndex($) = 0;
m_array($) = new jvar<T> [initial_size];
m_arraySize($) = initial_size;
}
bool IsEmpty()
{
return m_headIndex($) >= m_tailIndex($);
}
size_t Count()
{
return m_tailIndex($) - m_headIndex($);
}
void push(T item)
{
size_t tail = m_tailIndex($);
if (tail <= m_headIndex($) + m_mask($))
{
m_array($)[tail & m_mask($)]($) = item;
m_tailIndex($) = tail + 1;
}
else
{
m_foreignLock.lock($);
size_t head = m_headIndex($);
size_t count = Count();
if (count >= m_mask($))
{
size_t arraySize = m_arraySize($);
size_t mask = m_mask($);
jvar<T>* newArray = new jvar<T> [arraySize * 2];
jvar<T>* arr = m_array($);
for (size_t i = 0; i != count; ++i)
newArray[i]($) = arr[(i + head) & mask]($);
m_array($) = newArray;
m_arraySize($) = arraySize * 2;
m_headIndex($) = 0;
m_tailIndex($) = count;
tail = count;
m_mask($) = (mask * 2) | 1;
}
m_array($)[tail & m_mask($)]($) = item;
m_tailIndex($) = tail + 1;
m_foreignLock.unlock($);
}
}
bool pop(T& item)
{
size_t tail = m_tailIndex($);
if (tail == 0)
return false;
tail -= 1;
m_tailIndex($) = tail;
if (m_headIndex($) <= tail)
{
item = m_array($)[tail & m_mask($)]($);
return true;
}
else
{
m_foreignLock.lock($);
if (m_headIndex($) <= tail)
{
item = m_array($)[tail & m_mask($)]($);
m_foreignLock.unlock($);
return true;
}
else
{
m_tailIndex($) = tail + 1;
m_foreignLock.unlock($);
return false;
}
}
}
bool steal(T& item)
{
if (false == m_foreignLock.try_lock($))
return false;
size_t head = m_headIndex($);
m_headIndex($) = head + 1;
if (head < m_tailIndex($))
{
item = m_array($)[head & m_mask($)]($);
m_foreignLock.unlock($);
return true;
}
else
{
m_headIndex($) = head;
m_foreignLock.unlock($);
return false;
}
}
private:
static size_t const initial_size = 2;
jvar<jvar<T>*> m_array;
jvar<size_t> m_mask;
jvar<size_t> m_arraySize;
jvolatile<size_t> m_headIndex;
jvolatile<size_t> m_tailIndex;
mutex m_foreignLock;
};
struct ws_deque_test : rl::test_suite<ws_deque_test, 2>
{
ws_deque<int> q;
bool state [2];
void before()
{
state[0] = true;
state[1] = true;
}
void after()
{
RL_ASSERT(state[0] == false);
RL_ASSERT(state[1] == false);
}
void thread(unsigned index)
{
if (0 == index)
{
q.push(1);
q.push(2);
int item = 0;
bool res = q.pop(item);
RL_ASSERT(res && item == 2);
RL_ASSERT(state[1]);
state[1] = false;
item = 0;
res = q.pop(item);
if (res)
{
RL_ASSERT(state[0]);
state[0] = false;
}
item = 0;
res = q.pop(item);
RL_ASSERT(res == false);
}
else
{
int item = 0;
bool res = q.steal(item);
if (res)
{
RL_ASSERT(item == 1);
RL_ASSERT(state[0]);
state[0] = false;
}
}
}
};
int main()
{
rl::simulate<ws_deque_test>();
}
@@ -0,0 +1,20 @@
Microsoft Visual Studio Solution File, Format Version 9.00
# Visual Studio 2005
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "java_ws_deque", "java_ws_deque.vcproj", "{D4756EE9-3953-4E17-B1B5-E89F853303C1}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Win32 = Debug|Win32
Release|Win32 = Release|Win32
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{D4756EE9-3953-4E17-B1B5-E89F853303C1}.Debug|Win32.ActiveCfg = Debug|Win32
{D4756EE9-3953-4E17-B1B5-E89F853303C1}.Debug|Win32.Build.0 = Debug|Win32
{D4756EE9-3953-4E17-B1B5-E89F853303C1}.Release|Win32.ActiveCfg = Release|Win32
{D4756EE9-3953-4E17-B1B5-E89F853303C1}.Release|Win32.Build.0 = Release|Win32
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
EndGlobal
@@ -0,0 +1,205 @@
<?xml version="1.0" encoding="windows-1251"?>
<VisualStudioProject
ProjectType="Visual C++"
Version="8,00"
Name="java_ws_deque"
ProjectGUID="{9E88433F-779E-4461-9963-35E3338873AC}"
RootNamespace="java_ws_deque"
Keyword="Win32Proj"
>
<Platforms>
<Platform
Name="Win32"
/>
</Platforms>
<ToolFiles>
</ToolFiles>
<Configurations>
<Configuration
Name="Debug|Win32"
OutputDirectory="$(SolutionDir)$(ConfigurationName)"
IntermediateDirectory="$(ConfigurationName)"
ConfigurationType="1"
CharacterSet="1"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
/>
<Tool
Name="VCCLCompilerTool"
Optimization="0"
PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE"
MinimalRebuild="true"
BasicRuntimeChecks="3"
RuntimeLibrary="3"
UsePrecompiledHeader="2"
WarningLevel="4"
DebugInformationFormat="4"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
LinkIncremental="2"
GenerateDebugInformation="true"
SubSystem="1"
TargetMachine="1"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCWebDeploymentTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
<Configuration
Name="Release|Win32"
OutputDirectory="$(SolutionDir)$(ConfigurationName)"
IntermediateDirectory="$(ConfigurationName)"
ConfigurationType="1"
CharacterSet="1"
WholeProgramOptimization="1"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
/>
<Tool
Name="VCCLCompilerTool"
PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE"
RuntimeLibrary="2"
UsePrecompiledHeader="2"
WarningLevel="4"
DebugInformationFormat="3"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
LinkIncremental="1"
GenerateDebugInformation="true"
SubSystem="1"
OptimizeReferences="2"
EnableCOMDATFolding="2"
TargetMachine="1"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCWebDeploymentTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
</Configurations>
<References>
</References>
<Files>
<File
RelativePath="..\java_ws_deque.cpp"
>
</File>
<File
RelativePath="..\stdafx.cpp"
>
<FileConfiguration
Name="Debug|Win32"
>
<Tool
Name="VCCLCompilerTool"
UsePrecompiledHeader="1"
ObjectFile="$(IntDir)\$(InputName)1.obj"
XMLDocumentationFileName="$(IntDir)\$(InputName)1.xdc"
/>
</FileConfiguration>
<FileConfiguration
Name="Release|Win32"
>
<Tool
Name="VCCLCompilerTool"
UsePrecompiledHeader="1"
ObjectFile="$(IntDir)\$(InputName)1.obj"
XMLDocumentationFileName="$(IntDir)\$(InputName)1.xdc"
/>
</FileConfiguration>
</File>
<File
RelativePath="..\stdafx.h"
>
</File>
</Files>
<Globals>
</Globals>
</VisualStudioProject>
@@ -0,0 +1,2 @@
#include "stdafx.h"
@@ -0,0 +1,7 @@
#pragma once
#include "../../relacy/pch.hpp"
@@ -0,0 +1,511 @@
#include "stdafx.h"
#ifdef RL_TEST
#define ATOMIC(x) rl::atomic<x>
#define VAR(x) rl::var<x>
#define ATOMIC_FETCH_ADD(x, v) x($).fetch_add(v)
#define ATOMIC_COMPARE_EXCHANGE(x, c, v) x($).compare_exchange(c, v)
#define LOAD_ACQ(x) x($).load(rl::memory_order_acquire)
#define STORE_REL(x, v) x($).store(v, rl::memory_order_release)
#else
#define ATOMIC(x) x volatile
#define VAR(x) x
#define ATOMIC_FETCH_ADD(x, v) _InterlockedExchangeAdd((long*)&x, v)
#define ATOMIC_COMPARE_EXCHANGE(x, c, v) interlocked_compare_exchange(x, c, v)
#define LOAD_ACQ(x) x
#define STORE_REL(x, v) x = v
template<typename T>
bool interlocked_compare_exchange(T& x, T& c, T v)
{
T c0 = _InterlockedCompareExchange((long*)&x), v, c);
if (c0 == c)
{
return true;
}
else
{
c = c0;
return false;
}
}
#endif
//#include "pcx.h"
/*
template<typename T>
class mpmcq
{
public:
mpmcq()
{
STORE_REL(head_, alloc_block());
STORE_REL(tail_, LOAD_ACQ(head_));
}
void enqueue(T v)
{
for (;;)
{
block* b = LOAD_ACQ(head_);
unsigned raw = ATOMIC_FETCH_ADD(b->state_, state_head_inc);
unsigned idx = raw >> state_head_pos;
if (idx < item_count)
{
STORE_REL(b->data_[idx], v);
return;
}
unsigned last = raw & state_last_msk;
if (0 == last)
{
ATOMIC_COMPARE_EXCHANGE(head_, b, b+1);
}
else
{
block* b2 = LOAD_ACQ(b->next_);
if (b2)
{
ATOMIC_COMPARE_EXCHANGE(head_, b, b2);
}
else
{
b2 = alloc_block();
block* b3 = 0;
if (ATOMIC_COMPARE_EXCHANGE(b->next_, b3, b2))
{
ATOMIC_COMPARE_EXCHANGE(head_, b, b2);
}
else
{
for (;;)
{
b = LOAD_ACQ(head_);
while (0 == (LOAD_ACQ(b->state_) & state_last_msk))
b = b + 1;
while (LOAD_ACQ(b->next_))
b = LOAD_ACQ(b->next_) + block_count - 1;
b3 = 0;
if (ATOMIC_COMPARE_EXCHANGE(b->next_, b3, b2))
break;
}
}
}
}
}
}
T dequeue()
{
for (;;)
{
block* b = LOAD_ACQ(tail_);
unsigned cmp = LOAD_ACQ(b->state_);
unsigned tail = cmp & (state_last_msk - 1);
if (tail < item_count)
{
unsigned head = cmp >> state_head_pos;
if (tail < head)
{
unsigned xchg = cmp + state_tail_inc;
if (ATOMIC_COMPARE_EXCHANGE(b->state_, cmp, xchg))
{
for (;;)
{
T v = LOAD_ACQ(b->data_[tail]);
if (v != T())
return v;
rl::yield($);
}
}
}
else
{
return T();
}
}
else
{
unsigned last = cmp & state_last_msk;
if (0 == last)
{
ATOMIC_COMPARE_EXCHANGE(tail_, b, b+1);
}
else
{
block* b2 = LOAD_ACQ(b->next_);
if (0 == b2)
return T();
ATOMIC_COMPARE_EXCHANGE(tail_, b, b2);
}
}
}
}
private:
static unsigned const state_head_pos = 7;
static unsigned const state_head_inc = 1 << state_head_pos;
static unsigned const state_last_msk = 1 << 6;
static unsigned const state_tail_inc = 1 << 0;
static unsigned const item_count = 2;
static unsigned const block_count = 16;
struct block
{
//unsigned head_ : 24;
//unsigned last_ : 1;
//unsigned tail_ : 7;
ATOMIC(unsigned) state_;
ATOMIC(block*) next_;
ATOMIC(T) data_ [item_count];
};
struct superblock
{
block blocks_ [block_count];
};
char pad0_ [64];
ATOMIC(block*) head_;
char pad1_ [64];
ATOMIC(block*) tail_;
char pad2_ [64];
block* alloc_block()
{
superblock* sb = RL_NEW(superblock);
for (int x = 0; x != block_count; ++x)
{
block* b = &sb->blocks_[x];
STORE_REL(b->state_, 0);
STORE_REL(b->next_, 0);
for (int y = 0; y != item_count; ++y)
{
STORE_REL(b->data_[y], 0);
}
}
STORE_REL(sb->blocks_[block_count - 1].state_, 1 * state_head_inc + 1 * state_tail_inc + state_last_msk);
return &sb->blocks_[0];
}
};
struct test_mpmc : rl::test_suite<test_mpmc, 6>
{
mpmcq<int> q;
void thread(unsigned idx)
{
if (idx < thread_count / 2)
{
for (int i = 0; i != 2; ++i)
q.enqueue(1);
}
else
{
for (int i = 0; i != 2; ++i)
q.dequeue();
}
}
};
*/
struct thread_node
{
rl::var<thread_node*> next;
rl::var<size_t> count;
rl::var<size_t> unconsumed;
rl::HANDLE sema;
rl::CRITICAL_SECTION mtx;
};
void on_thread_exit(thread_node*& t_thread_node)
{
thread_node* head = t_thread_node;
thread_node* my = 0;
if (head)
{
rl::EnterCriticalSection(&head->mtx, $);
std::atomic_thread_fence($)(std::memory_order_seq_cst);
if (head->next($))
{
my = head->next($);
head->next($) = (thread_node*)my->next($);
}
else
{
my = head;
}
std::atomic_thread_fence($)(std::memory_order_seq_cst);
rl::LeaveCriticalSection(&head->mtx, $);
while (my->unconsumed($))
{
rl::WaitForSingleObject(my->sema, rl::RL_INFINITE, $);
my->unconsumed($) -= 1;
}
rl::DeleteCriticalSection(&my->mtx, $);
rl::CloseHandle(my->sema, $);
RL_DELETE(my);
}
}
struct eventcount
{
eventcount()
{
root($) = 0;
rl::InitializeCriticalSection(&mtx, $);
}
~eventcount()
{
rl::DeleteCriticalSection(&mtx, $);
}
void prepare_wait(thread_node*& t_thread_node)
{
thread_node* my = 0;
thread_node* head = t_thread_node;
if (head)
{
rl::EnterCriticalSection(&head->mtx, $);
std::atomic_thread_fence($)(std::memory_order_seq_cst);
//RL_ASSERT(head->status == stat_root);
RL_ASSERT (root($) != head);
if (head->next($))
{
my = head->next($);
head->next($) = (thread_node*)my->next($);
my->next($) = 0;
//node_status st;
//if (stat_bucket != (st = (node_status)_InterlockedExchange(&my->status, stat_private)))
// __asm int 3;
RL_ASSERT (0 == my->count($));
}
else
{
my = head;
//node_status st;
//if (stat_root != (st = (node_status)_InterlockedExchange(&my->status, stat_private)))
// __asm int 3;
RL_ASSERT(0 == my->count($));
}
std::atomic_thread_fence($)(std::memory_order_seq_cst);
rl::LeaveCriticalSection(&head->mtx, $);
}
else
{
my = RL_NEW thread_node;
my->next($) = 0;
my->count($) = 0;
my->unconsumed($) = 0;
my->sema = rl::CreateSemaphore(0, 0, LONG_MAX, 0, $);
//my->status = stat_private;
rl::InitializeCriticalSection(&my->mtx, $);
}
while (my->unconsumed($))
{
rl::WaitForSingleObject(my->sema, rl::RL_INFINITE, $);
my->unconsumed($) -= 1;
}
RL_ASSERT(0 == my->next($));
RL_ASSERT(0 == my->count($));
//if (my->status != stat_private) __asm int 3;
rl::EnterCriticalSection(&mtx, $);
std::atomic_thread_fence($)(std::memory_order_seq_cst);
RL_ASSERT(root($) != my);
if (root($))
{
my->next($) = (thread_node*)((thread_node*)root($))->next($);
((thread_node*)root($))->next($) = my;
//node_status st;
//if (stat_private != (st = (node_status)_InterlockedExchange(&my->status, stat_bucket)))
// __asm int 3;
my = root($);
}
else
{
root($) = my;
//node_status st;
//if (stat_private != (st = (node_status)_InterlockedExchange(&my->status, stat_root)))
// __asm int 3;
}
((thread_node*)root($))->count($) += 1;
std::atomic_thread_fence($)(std::memory_order_seq_cst);
rl::LeaveCriticalSection(&mtx, $);
t_thread_node = my;
}
void wait(thread_node*& t_thread_node)
{
thread_node* head = t_thread_node;
if (head == root($))
{
rl::WaitForSingleObject(head->sema, rl::RL_INFINITE, $);
}
else
{
rl::EnterCriticalSection(&head->mtx, $);
std::atomic_thread_fence($)(std::memory_order_seq_cst);
head->unconsumed($) += 1;
std::atomic_thread_fence($)(std::memory_order_seq_cst);
rl::LeaveCriticalSection(&head->mtx, $);
}
}
void retire_wait(thread_node*& t_thread_node)
{
thread_node* head = t_thread_node;
if (head == root($))
{
rl::EnterCriticalSection(&mtx, $);
std::atomic_thread_fence($)(std::memory_order_seq_cst);
if (head == root($))
{
thread_node* my = 0;
head->count($) -= 1;
if (head->next($))
{
my = head->next($);
head->next($) = (thread_node*)my->next($);
my->next($) = 0;
}
else
{
my = head;
root($) = 0;
}
std::atomic_thread_fence($)(std::memory_order_seq_cst);
rl::LeaveCriticalSection(&mtx, $);
//my->status = stat_root;
t_thread_node = my;
return;
}
std::atomic_thread_fence($)(std::memory_order_seq_cst);
rl::LeaveCriticalSection(&mtx, $);
}
rl::EnterCriticalSection(&head->mtx, $);
std::atomic_thread_fence($)(std::memory_order_seq_cst);
head->unconsumed($) += 1;
std::atomic_thread_fence($)(std::memory_order_seq_cst);
rl::LeaveCriticalSection(&head->mtx, $);
}
void signal_all()
{
//std::
//_mm_mfence();
thread_node* head = root($);
if (0 == head)
return;
rl::EnterCriticalSection(&mtx, $);
std::atomic_thread_fence($)(std::memory_order_seq_cst);
if (head != root($))
{
std::atomic_thread_fence($)(std::memory_order_seq_cst);
rl::LeaveCriticalSection(&mtx, $);
return;
}
size_t count = head->count($);
head->count($) = 0;
root($) = 0;
std::atomic_thread_fence($)(std::memory_order_seq_cst);
rl::LeaveCriticalSection(&mtx, $);
rl::ReleaseSemaphore(head->sema, count, 0, $);
}
std::atomic<thread_node*> root;
rl::CRITICAL_SECTION mtx;
};
struct test_ec : rl::test_suite<test_ec, 8>
{
std::atomic<int> x [2];
eventcount ec;
void before()
{
x[0]($) = 0;
x[1]($) = 0;
}
void thread(unsigned idx)
{
if (idx < 4)
{
for (int i = 0; i != 3; ++i)
{
x[idx % 2]($).fetch_add(1);
ec.signal_all();
}
}
else
{
thread_node* my = 0;
for (int i = 0; i != 3; ++i)
{
for (;;)
{
int cmp = x[idx % 2]($);
if (cmp > 0)
{
if (x[idx % 2]($).compare_exchange(cmp, cmp - 1))
break;
}
else
{
for (;;)
{
ec.prepare_wait(my);
cmp = x[idx % 2]($);
if (cmp > 0)
{
ec.retire_wait(my);
break;
}
ec.wait(my);
cmp = x[idx % 2]($);
if (cmp > 0)
{
break;
}
}
}
}
}
on_thread_exit(my);
}
}
};
int main()
{
rl::test_params p;
p.iteration_count = 20000000;
p.initial_state = "10000000";
rl::simulate<test_ec>(p);
}
@@ -0,0 +1,20 @@
Microsoft Visual Studio Solution File, Format Version 9.00
# Visual Studio 2005
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "mpmc", "mpmc.vcproj", "{ECB64178-A35E-4EB2-9EB0-BD72D6F7B6E4}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Win32 = Debug|Win32
Release|Win32 = Release|Win32
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{ECB64178-A35E-4EB2-9EB0-BD72D6F7B6E4}.Debug|Win32.ActiveCfg = Debug|Win32
{ECB64178-A35E-4EB2-9EB0-BD72D6F7B6E4}.Debug|Win32.Build.0 = Debug|Win32
{ECB64178-A35E-4EB2-9EB0-BD72D6F7B6E4}.Release|Win32.ActiveCfg = Release|Win32
{ECB64178-A35E-4EB2-9EB0-BD72D6F7B6E4}.Release|Win32.Build.0 = Release|Win32
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
EndGlobal
@@ -0,0 +1,207 @@
<?xml version="1.0" encoding="windows-1251"?>
<VisualStudioProject
ProjectType="Visual C++"
Version="8,00"
Name="mpmc"
ProjectGUID="{ECB64178-A35E-4EB2-9EB0-BD72D6F7B6E4}"
RootNamespace="mpmc"
Keyword="Win32Proj"
>
<Platforms>
<Platform
Name="Win32"
/>
</Platforms>
<ToolFiles>
</ToolFiles>
<Configurations>
<Configuration
Name="Debug|Win32"
OutputDirectory="$(SolutionDir)$(ConfigurationName)"
IntermediateDirectory="$(ConfigurationName)"
ConfigurationType="1"
CharacterSet="1"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
/>
<Tool
Name="VCCLCompilerTool"
Optimization="0"
PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE"
MinimalRebuild="true"
BasicRuntimeChecks="3"
RuntimeLibrary="3"
UsePrecompiledHeader="2"
WarningLevel="4"
Detect64BitPortabilityProblems="false"
DebugInformationFormat="4"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
LinkIncremental="2"
GenerateDebugInformation="true"
SubSystem="1"
TargetMachine="1"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCWebDeploymentTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
<Configuration
Name="Release|Win32"
OutputDirectory="$(SolutionDir)$(ConfigurationName)"
IntermediateDirectory="$(ConfigurationName)"
ConfigurationType="1"
CharacterSet="1"
WholeProgramOptimization="1"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
/>
<Tool
Name="VCCLCompilerTool"
PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE"
RuntimeLibrary="2"
UsePrecompiledHeader="2"
WarningLevel="4"
Detect64BitPortabilityProblems="false"
DebugInformationFormat="3"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
LinkIncremental="1"
GenerateDebugInformation="true"
SubSystem="1"
OptimizeReferences="2"
EnableCOMDATFolding="2"
TargetMachine="1"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCWebDeploymentTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
</Configurations>
<References>
</References>
<Files>
<File
RelativePath="..\mpmc.cpp"
>
</File>
<File
RelativePath="..\pcx.h"
>
</File>
<File
RelativePath="..\stdafx.cpp"
>
<FileConfiguration
Name="Debug|Win32"
>
<Tool
Name="VCCLCompilerTool"
UsePrecompiledHeader="1"
/>
</FileConfiguration>
<FileConfiguration
Name="Release|Win32"
>
<Tool
Name="VCCLCompilerTool"
UsePrecompiledHeader="1"
/>
</FileConfiguration>
</File>
<File
RelativePath="..\stdafx.h"
>
</File>
</Files>
<Globals>
</Globals>
</VisualStudioProject>
@@ -0,0 +1,481 @@
#pragma once
#include <intrin.h>
#pragma intrinsic (_InterlockedExchangeAdd)
#pragma intrinsic (_InterlockedCompareExchange)
//#define PCX_DEBUG
#ifdef PCX_DEBUG
#include <sstream>
#include <windows.h>
#endif
namespace rl
{
size_t const cacheline_size = 64;
struct pcx_node
{
typedef void (*pcx_dtor_t)(pcx_node*);
ATOMIC(pcx_node*) pcx_next_;
ATOMIC(pcx_dtor_t) pcx_dtor_;
};
namespace pcx_int
{
unsigned const word_bits = 32;
unsigned const collector_bits = 4;
unsigned const collector_count = 1 << collector_bits;
unsigned const counter_inc = 1 << (collector_bits * 2);
unsigned const is_current_inc = 1;
unsigned const back_link_inc = 2;
struct master;
struct collector;
struct local_collector
{
pcx_node* defer_head_;
pcx_node defer_tail_;
unsigned defer_size_;
};
struct thread_int
{
pcx_int::master* master_;
pcx_int::collector* collectors_;
unsigned recursion_count_;
unsigned is_acquired_;
unsigned collector_index_;
unsigned last_seen_collector_index_;
unsigned flush_tail_;
pcx_node* defer_head_;
pcx_node defer_tail_;
unsigned defer_size_;
unsigned promote_;
local_collector local_collectors_ [collector_count];
};
}
class pcx_thread : private pcx_int::thread_int
{
public:
static pcx_thread& get();
void acquire();
void release();
void defer(pcx_node* node, pcx_node::pcx_dtor_t dtor);
void flush();
void promote();
void quiescent();
void init();
void deinit();
private:
unsigned acquire_impl();
void release_impl(unsigned, unsigned);
void flush_impl();
void local_flush();
void quiescent_impl();
friend void init();
friend void deinit();
friend void thread_callback(bool);
};
namespace pcx_int
{
struct master
{
char pad0_ [64];
unsigned garbage_threshold_;
char pad1_ [64];
struct state_part
{
unsigned current_collector_ : collector_bits;
unsigned collector_tail_ : collector_bits;
unsigned outer_counter_ : word_bits - 2 * collector_bits;
};
union state
{
long whole_;
state_part part_;
};
state state_;
char pad2_ [64];
state state_copy_;
char pad3_ [64];
};
struct collector
{
char pad0_ [64];
pcx_node* defer_list_head_;
unsigned defer_list_size_;
char pad1_ [64];
struct state_part
{
unsigned is_current_ : 1;
unsigned back_link_ : 1;
unsigned pad_ : collector_bits * 2 - 2;
unsigned inner_counter_ : word_bits - 2 * collector_bits;
};
union state
{
long whole_;
state_part part_;
};
state state_;
char pad2_ [64];
};
__declspec(selectany)
master g_master;
__declspec(selectany)
collector g_collectors [collector_count];
__declspec(selectany, thread)
thread_int* g_thread_instance;
typedef void (__stdcall nt_tls_cb_t)(void*, unsigned long, void*);
nt_tls_cb_t on_tls_callback;
#pragma data_seg(push, old_seg)
#pragma data_seg(".CRT$XLB")
__declspec(selectany, dllexport)
nt_tls_cb_t* volatile p_thread_callback = on_tls_callback;
#pragma data_seg(pop, old_seg)
inline void __stdcall on_tls_callback(void*, unsigned long reason, void*)
{
if (1 == reason)
{
init();
thread_callback(true);
}
else if (0 == reason)
{
thread_callback(false);
deinit();
}
if (2 == reason)
{
thread_callback(true);
}
else if (3 == reason)
{
thread_callback(false);
}
}
}
inline void init()
{
using namespace pcx_int;
master& m = g_master;
m.garbage_threshold_ = 128;
m.state_.part_.current_collector_ = 0;
m.state_.part_.collector_tail_ = 0;
m.state_.part_.outer_counter_ = 0;
m.state_copy_.part_.current_collector_ = 0;
m.state_copy_.part_.collector_tail_ = 0;
m.state_copy_.part_.outer_counter_ = 0;
for (unsigned i = 0; i != collector_count; ++i)
{
collector& c = g_collectors[i];
c.defer_list_head_ = 0;
c.defer_list_size_ = 0;
c.state_.part_.is_current_ = 1;
c.state_.part_.back_link_ = 1;
c.state_.part_.inner_counter_ = 0;
}
g_collectors[0].state_.part_.back_link_ = 0;
}
inline void deinit()
{
using namespace pcx_int;
pcx_thread::get().release_impl(g_master.state_.part_.current_collector_, is_current_inc);
}
inline void thread_callback(bool init)
{
if (init)
{
g_thread_instance = RL_NEW pcx_thread ();
pcx_thread::get().init();
}
else
{
pcx_thread::get().deinit();
RL_DELETE(g_thread_instance);
g_thread_instance = 0;
}
}
inline pcx_thread& pcx_thread::get()
{
return static_cast<pcx_thread&>(*pcx_int::g_thread_instance);
}
inline unsigned pcx_thread::acquire_impl()
{
using namespace pcx_int;
long const prev =
_InterlockedExchangeAdd(
&master_->state_.whole_, counter_inc);
master::state_part u = {prev};
#ifdef PCX_DEBUG
std::ostringstream ss;
ss << "[PCX] thread " << this << " acquire " << u.current_collector_ << "\n";
OutputDebugStringA(ss.str().c_str());
#endif
if (u.current_collector_ == flush_tail_
&& local_collectors_[flush_tail_].defer_size_)
{
local_flush();
}
return u.current_collector_;
}
inline void pcx_thread::release_impl(unsigned index, unsigned count)
{
using namespace pcx_int;
collector& c = collectors_[index];
unsigned const prev =
_InterlockedExchangeAdd(
&c.state_.whole_, (unsigned)-(int)count);
#ifdef PCX_DEBUG
std::ostringstream ss;
ss << "[PCX] thread " << this << " release " << index << "\n";
OutputDebugStringA(ss.str().c_str());
#endif
if (0 == prev - count)
{
pcx_node* curr = c.defer_list_head_;
while (curr)
{
pcx_node* next = curr->pcx_next_;
curr->pcx_dtor_(curr);
curr = next;
}
c.defer_list_head_ = 0;
c.defer_list_size_ = 0;
c.state_.part_.back_link_ = 1;
c.state_.part_.is_current_ = 1;
long u;
if (index != collector_count - 1)
u = collector_count;
else
u = -(long)(collector_count * (collector_count - 1));
_InterlockedExchangeAdd(&master_->state_.whole_, u);
release_impl((index + 1) % collector_count, back_link_inc);
}
}
inline void pcx_thread::flush_impl()
{
using namespace pcx_int;
_mm_mfence();
master::state state = master_->state_;
last_seen_collector_index_ = state.part_.current_collector_;
collector& gc = collectors_[state.part_.current_collector_];
local_collector& lc = local_collectors_[state.part_.current_collector_];
lc.defer_head_->pcx_next_ = defer_tail_.pcx_next_;
lc.defer_head_ = defer_tail_.pcx_next_;
lc.defer_size_ += defer_size_;
defer_head_ = &defer_tail_;
defer_tail_.pcx_next_ = 0;
defer_size_ = 0;
if (master_->garbage_threshold_ < lc.defer_size_ || promote_)
{
master::state cmp;
master::state val;
do
{
cmp = master_->state_;
if (cmp.part_.current_collector_ != last_seen_collector_index_)
{
promote_ = 0;
return;
}
unsigned next_index = (last_seen_collector_index_ + 1) % collector_count;
if (cmp.part_.collector_tail_ == next_index)
return;
val = cmp;
val.part_.current_collector_ += 1;
val.part_.outer_counter_ = 0;
}
while (cmp.whole_ != _InterlockedCompareExchange(
(long*)&master_->state_.whole_, val.whole_, cmp.whole_));
last_seen_collector_index_ = val.part_.current_collector_;
promote_ = 0;
_InterlockedIncrement((long*)&master_->state_copy_.whole_);
_InterlockedExchangeAdd((long*)&gc.state_.whole_,
cmp.part_.outer_counter_ * counter_inc - is_current_inc);
}
}
__declspec(noinline)
inline void pcx_thread::local_flush()
{
using namespace pcx_int;
if (flush_tail_ == master_->state_.part_.collector_tail_)
return;
#ifdef PCX_DEBUG
std::ostringstream ss;
ss << "[PCX] thread " << this << " flush " << flush_tail_ << "\n";
OutputDebugStringA(ss.str().c_str());
#endif
local_collector& lc = local_collectors_[flush_tail_];
pcx_node* curr = lc.defer_tail_.pcx_next_;
while (curr)
{
#ifdef PCX_DEBUG
std::ostringstream ss;
ss << "[PCX] thread " << this << " destroy " << curr << "\n";
OutputDebugStringA(ss.str().c_str());
#endif
pcx_node* next = curr->pcx_next_;
curr->pcx_dtor_(curr);
curr = next;
}
lc.defer_head_ = &lc.defer_tail_;
lc.defer_tail_.pcx_next_ = 0;
lc.defer_size_ = 0;
flush_tail_ = (flush_tail_ + 1) % collector_count;
}
__declspec(noinline)
inline void pcx_thread::quiescent_impl()
{
using namespace pcx_int;
if (defer_size_)
flush_impl();
release_impl(collector_index_, counter_inc);
collector_index_ = acquire_impl();
}
inline void pcx_thread::acquire()
{
using namespace pcx_int;
recursion_count_ += 1;
if (1 != recursion_count_)
return;
if (is_acquired_)
return;
collector_index_ = acquire_impl();
last_seen_collector_index_ = collector_index_;
is_acquired_ = 1;
}
inline void pcx_thread::release()
{
using namespace pcx_int;
recursion_count_ -= 1;
if (0 == recursion_count_)
{
if (master_->state_copy_.part_.current_collector_ != collector_index_
|| promote_)
{
if (defer_size_)
flush_impl();
release_impl(collector_index_, counter_inc);
is_acquired_ = 0;
}
}
if (flush_tail_ != last_seen_collector_index_)
{
local_flush();
}
}
inline void pcx_thread::quiescent()
{
if (master_->state_copy_.part_.current_collector_ != collector_index_
|| promote_)
{
quiescent_impl();
}
if (flush_tail_ != last_seen_collector_index_)
{
local_flush();
}
}
inline void pcx_thread::defer(pcx_node* node, pcx_node::pcx_dtor_t dtor)
{
using namespace pcx_int;
node->pcx_next_ = 0;
node->pcx_dtor_ = dtor;
defer_head_->pcx_next_ = node;
defer_head_ = node;
defer_size_ += 1;
}
inline void pcx_thread::flush()
{
using namespace pcx_int;
if (recursion_count_)
return;
if (0 == is_acquired_)
return;
if (defer_size_)
flush_impl();
release_impl(collector_index_, counter_inc);
is_acquired_ = 0;
}
inline void pcx_thread::promote()
{
promote_ = 1;
}
inline void pcx_thread::init()
{
using namespace pcx_int;
master_ = &g_master;
collectors_ = g_collectors;
defer_head_ = &defer_tail_;
defer_tail_.pcx_next_ = 0;
for (unsigned i = 0; i != collector_count; ++i)
{
local_collectors_[i].defer_head_ = &local_collectors_[i].defer_tail_;
}
}
inline void pcx_thread::deinit()
{
flush();
}
}
@@ -0,0 +1,8 @@
// stdafx.cpp : source file that includes just the standard includes
// ws_deque.pch will be the pre-compiled header
// stdafx.obj will contain the pre-compiled type information
#include "stdafx.h"
// TODO: reference any additional headers you need in STDAFX.H
// and not in this file
@@ -0,0 +1,10 @@
#pragma once
#pragma warning (disable: 4201)
//#define RL_GC
#define RL_MSVC_OUTPUT
#include "../../relacy/pch.hpp"
#include "../../relacy/relacy_std.hpp"
@@ -0,0 +1,20 @@
Microsoft Visual Studio Solution File, Format Version 9.00
# Visual Studio 2005
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "mutex_business_logic", "mutex_business_logic.vcproj", "{D4756EE9-3953-4E17-B1B5-E89F853303C1}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Win32 = Debug|Win32
Release|Win32 = Release|Win32
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{D4756EE9-3953-4E17-B1B5-E89F853303C1}.Debug|Win32.ActiveCfg = Debug|Win32
{D4756EE9-3953-4E17-B1B5-E89F853303C1}.Debug|Win32.Build.0 = Debug|Win32
{D4756EE9-3953-4E17-B1B5-E89F853303C1}.Release|Win32.ActiveCfg = Release|Win32
{D4756EE9-3953-4E17-B1B5-E89F853303C1}.Release|Win32.Build.0 = Release|Win32
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
EndGlobal
@@ -0,0 +1,205 @@
<?xml version="1.0" encoding="windows-1251"?>
<VisualStudioProject
ProjectType="Visual C++"
Version="8,00"
Name="mutex_business_logic"
ProjectGUID="{B03A7216-E196-44C6-8861-C77D90055512}"
RootNamespace="mutex_business_logic"
Keyword="Win32Proj"
>
<Platforms>
<Platform
Name="Win32"
/>
</Platforms>
<ToolFiles>
</ToolFiles>
<Configurations>
<Configuration
Name="Debug|Win32"
OutputDirectory="$(SolutionDir)$(ConfigurationName)"
IntermediateDirectory="$(ConfigurationName)"
ConfigurationType="1"
CharacterSet="1"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
/>
<Tool
Name="VCCLCompilerTool"
Optimization="0"
PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE"
MinimalRebuild="true"
BasicRuntimeChecks="3"
RuntimeLibrary="3"
UsePrecompiledHeader="2"
WarningLevel="4"
DebugInformationFormat="4"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
LinkIncremental="2"
GenerateDebugInformation="true"
SubSystem="1"
TargetMachine="1"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCWebDeploymentTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
<Configuration
Name="Release|Win32"
OutputDirectory="$(SolutionDir)$(ConfigurationName)"
IntermediateDirectory="$(ConfigurationName)"
ConfigurationType="1"
CharacterSet="1"
WholeProgramOptimization="1"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
/>
<Tool
Name="VCCLCompilerTool"
PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE"
RuntimeLibrary="2"
UsePrecompiledHeader="2"
WarningLevel="4"
DebugInformationFormat="3"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
LinkIncremental="1"
GenerateDebugInformation="true"
SubSystem="1"
OptimizeReferences="2"
EnableCOMDATFolding="2"
TargetMachine="1"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCWebDeploymentTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
</Configurations>
<References>
</References>
<Files>
<File
RelativePath="..\mutex_business_logic.cpp"
>
</File>
<File
RelativePath="..\stdafx.cpp"
>
<FileConfiguration
Name="Debug|Win32"
>
<Tool
Name="VCCLCompilerTool"
UsePrecompiledHeader="1"
ObjectFile="$(IntDir)\$(InputName)1.obj"
XMLDocumentationFileName="$(IntDir)\$(InputName)1.xdc"
/>
</FileConfiguration>
<FileConfiguration
Name="Release|Win32"
>
<Tool
Name="VCCLCompilerTool"
UsePrecompiledHeader="1"
ObjectFile="$(IntDir)\$(InputName)1.obj"
XMLDocumentationFileName="$(IntDir)\$(InputName)1.xdc"
/>
</FileConfiguration>
</File>
<File
RelativePath="..\stdafx.h"
>
</File>
</Files>
<Globals>
</Globals>
</VisualStudioProject>
@@ -0,0 +1,131 @@
#include "stdafx.h"
#include "../../relacy/relacy_std.hpp"
class business_logic
{
public:
typedef unsigned account_id_t;
typedef double balance_t;
business_logic()
{
pthread_rwlock_init(&accounts_guard, 0);
}
~business_logic()
{
pthread_rwlock_destroy(&accounts_guard);
}
bool add_account(account_id_t acc_id, balance_t balance)
{
pthread_rwlock_wrlock(&accounts_guard);
if (accounts.find(acc_id) != accounts.end())
{
pthread_rwlock_unlock(&accounts_guard);
return false;
}
accounts[acc_id].balance = balance;
pthread_rwlock_unlock(&accounts_guard);
return true;
}
bool transfer_balance(account_id_t acc_id1, account_id_t acc_id2, balance_t amount)
{
if (acc_id1 == acc_id2)
return true;
pthread_rwlock_rdlock(&accounts_guard);
if (accounts.find(acc_id1) == accounts.end()
|| accounts.find(acc_id2) == accounts.end())
{
pthread_rwlock_unlock(&accounts_guard);
return false;
}
account_info& acc1 = accounts[acc_id1];
account_info& acc2 = accounts[acc_id2];
if (acc_id1 > acc_id2)
{
pthread_mutex_lock(&acc1.mtx);
pthread_mutex_lock(&acc2.mtx);
}
else
{
pthread_mutex_lock(&acc2.mtx);
pthread_mutex_lock(&acc1.mtx);
}
pthread_rwlock_unlock(&accounts_guard);
acc1.balance -= amount;
acc2.balance += amount;
pthread_mutex_unlock(&acc1.mtx);
pthread_mutex_unlock(&acc2.mtx);
return true;
}
private:
struct account_info
{
balance_t balance;
pthread_mutex_t mtx;
account_info()
: balance()
{
pthread_mutex_init(&mtx, 0);
}
account_info(account_info const& acc)
: balance(acc.balance)
{
pthread_mutex_init(&mtx, 0);
}
~account_info()
{
pthread_mutex_destroy(&mtx);
}
};
typedef std::map<account_id_t, account_info> account_map_t;
account_map_t accounts;
pthread_rwlock_t accounts_guard;
};
struct business_logic_test : rl::test_suite<business_logic_test, 2>
{
business_logic bl;
static size_t const account_count = 4;
void before()
{
for (size_t i = 0; i != account_count; ++i)
{
bool rv = bl.add_account(i, i * 10.0);
RL_ASSERT(rv);
}
}
void thread(unsigned /*index*/)
{
business_logic::account_id_t acc1 = rl::rand(account_count);
business_logic::account_id_t acc2 = rl::rand(account_count);
bool rv = bl.transfer_balance(acc1, acc2, 1.0);
RL_ASSERT(rv);
}
};
int main()
{
rl::simulate<business_logic_test>();
}
@@ -0,0 +1,2 @@
#include "stdafx.h"
@@ -0,0 +1,14 @@
#pragma once
#ifdef NDEBUG
# define _SECURE_SCL 0
#endif
#define RL_MSVC_OUTPUT
//#define RL_DEBUGBREAK_ON_FAILURE
#include "../../relacy/pch.hpp"
#include "../../relacy/relacy_std.hpp"
@@ -0,0 +1,20 @@
Microsoft Visual Studio Solution File, Format Version 9.00
# Visual Studio 2005
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "peterson", "peterson.vcproj", "{D4756EE9-3953-4E17-B1B5-E89F853303C1}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Win32 = Debug|Win32
Release|Win32 = Release|Win32
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{D4756EE9-3953-4E17-B1B5-E89F853303C1}.Debug|Win32.ActiveCfg = Debug|Win32
{D4756EE9-3953-4E17-B1B5-E89F853303C1}.Debug|Win32.Build.0 = Debug|Win32
{D4756EE9-3953-4E17-B1B5-E89F853303C1}.Release|Win32.ActiveCfg = Release|Win32
{D4756EE9-3953-4E17-B1B5-E89F853303C1}.Release|Win32.Build.0 = Release|Win32
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
EndGlobal
@@ -0,0 +1,205 @@
<?xml version="1.0" encoding="windows-1251"?>
<VisualStudioProject
ProjectType="Visual C++"
Version="8,00"
Name="peterson"
ProjectGUID="{D4756EE9-3953-4E17-B1B5-E89F853303C1}"
RootNamespace="peterson"
Keyword="Win32Proj"
>
<Platforms>
<Platform
Name="Win32"
/>
</Platforms>
<ToolFiles>
</ToolFiles>
<Configurations>
<Configuration
Name="Debug|Win32"
OutputDirectory="$(SolutionDir)$(ConfigurationName)"
IntermediateDirectory="$(ConfigurationName)"
ConfigurationType="1"
CharacterSet="1"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
/>
<Tool
Name="VCCLCompilerTool"
Optimization="0"
PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE"
MinimalRebuild="true"
BasicRuntimeChecks="3"
RuntimeLibrary="3"
UsePrecompiledHeader="2"
WarningLevel="4"
DebugInformationFormat="4"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
LinkIncremental="2"
GenerateDebugInformation="true"
SubSystem="1"
TargetMachine="1"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCWebDeploymentTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
<Configuration
Name="Release|Win32"
OutputDirectory="$(SolutionDir)$(ConfigurationName)"
IntermediateDirectory="$(ConfigurationName)"
ConfigurationType="1"
CharacterSet="1"
WholeProgramOptimization="1"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
/>
<Tool
Name="VCCLCompilerTool"
PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE"
RuntimeLibrary="2"
UsePrecompiledHeader="2"
WarningLevel="4"
DebugInformationFormat="3"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
LinkIncremental="1"
GenerateDebugInformation="true"
SubSystem="1"
OptimizeReferences="2"
EnableCOMDATFolding="2"
TargetMachine="1"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCWebDeploymentTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
</Configurations>
<References>
</References>
<Files>
<File
RelativePath="..\peterson.cpp"
>
</File>
<File
RelativePath="..\stdafx.cpp"
>
<FileConfiguration
Name="Debug|Win32"
>
<Tool
Name="VCCLCompilerTool"
UsePrecompiledHeader="1"
ObjectFile="$(IntDir)\$(InputName)1.obj"
XMLDocumentationFileName="$(IntDir)\$(InputName)1.xdc"
/>
</FileConfiguration>
<FileConfiguration
Name="Release|Win32"
>
<Tool
Name="VCCLCompilerTool"
UsePrecompiledHeader="1"
ObjectFile="$(IntDir)\$(InputName)1.obj"
XMLDocumentationFileName="$(IntDir)\$(InputName)1.xdc"
/>
</FileConfiguration>
</File>
<File
RelativePath="..\stdafx.h"
>
</File>
</Files>
<Globals>
</Globals>
</VisualStudioProject>
@@ -0,0 +1,20 @@
Microsoft Visual Studio Solution File, Format Version 10.00
# Visual Studio 2008
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "peterson", "peterson.vcproj", "{D4756EE9-3953-4E17-B1B5-E89F853303C1}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Win32 = Debug|Win32
Release|Win32 = Release|Win32
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{D4756EE9-3953-4E17-B1B5-E89F853303C1}.Debug|Win32.ActiveCfg = Debug|Win32
{D4756EE9-3953-4E17-B1B5-E89F853303C1}.Debug|Win32.Build.0 = Debug|Win32
{D4756EE9-3953-4E17-B1B5-E89F853303C1}.Release|Win32.ActiveCfg = Release|Win32
{D4756EE9-3953-4E17-B1B5-E89F853303C1}.Release|Win32.Build.0 = Release|Win32
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
EndGlobal
@@ -0,0 +1,200 @@
<?xml version="1.0" encoding="windows-1251"?>
<VisualStudioProject
ProjectType="Visual C++"
Version="9,00"
Name="peterson"
ProjectGUID="{D4756EE9-3953-4E17-B1B5-E89F853303C1}"
RootNamespace="peterson"
Keyword="Win32Proj"
TargetFrameworkVersion="131072"
>
<Platforms>
<Platform
Name="Win32"
/>
</Platforms>
<ToolFiles>
</ToolFiles>
<Configurations>
<Configuration
Name="Debug|Win32"
OutputDirectory="$(SolutionDir)$(ConfigurationName)"
IntermediateDirectory="$(ConfigurationName)"
ConfigurationType="1"
CharacterSet="1"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
/>
<Tool
Name="VCCLCompilerTool"
Optimization="0"
PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE"
MinimalRebuild="true"
BasicRuntimeChecks="3"
RuntimeLibrary="3"
UsePrecompiledHeader="2"
WarningLevel="4"
DebugInformationFormat="4"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
LinkIncremental="2"
GenerateDebugInformation="true"
SubSystem="1"
RandomizedBaseAddress="1"
DataExecutionPrevention="0"
TargetMachine="1"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
<Configuration
Name="Release|Win32"
OutputDirectory="$(SolutionDir)$(ConfigurationName)"
IntermediateDirectory="$(ConfigurationName)"
ConfigurationType="1"
CharacterSet="1"
WholeProgramOptimization="1"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
/>
<Tool
Name="VCCLCompilerTool"
PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE"
RuntimeLibrary="2"
UsePrecompiledHeader="2"
WarningLevel="4"
DebugInformationFormat="3"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
LinkIncremental="1"
GenerateDebugInformation="true"
SubSystem="1"
OptimizeReferences="2"
EnableCOMDATFolding="2"
RandomizedBaseAddress="1"
DataExecutionPrevention="0"
TargetMachine="1"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
</Configurations>
<References>
</References>
<Files>
<File
RelativePath="..\peterson.cpp"
>
</File>
<File
RelativePath="..\stdafx.cpp"
>
<FileConfiguration
Name="Debug|Win32"
>
<Tool
Name="VCCLCompilerTool"
UsePrecompiledHeader="1"
/>
</FileConfiguration>
<FileConfiguration
Name="Release|Win32"
>
<Tool
Name="VCCLCompilerTool"
UsePrecompiledHeader="1"
/>
</FileConfiguration>
</File>
<File
RelativePath="..\stdafx.h"
>
</File>
</Files>
<Globals>
</Globals>
</VisualStudioProject>
@@ -0,0 +1,469 @@
#include "stdafx.h"
#include "../../relacy/relacy_std.hpp"
#include "../../relacy/windows.h"
struct peterson_mutex_test : rl::test_suite<peterson_mutex_test, 2>
{
std::atomic<int> flag0;
std::atomic<int> flag1;
std::atomic<int> turn;
rl::var<int> data;
void before()
{
flag0($) = 0;
flag1($) = 0;
turn($) = 0;
}
void thread(unsigned index)
{
if (0 == index)
{
flag0($).store(1);
turn($).store(1);
while (flag1($).load()
&& 1 == turn($).load());
data($) = 1;
flag0($).store(0);
}
else
{
flag1($).store(1);
turn($).store(0);
while (flag0($).load()
&& 0 == turn($).load());
data($) = 2;
flag1($).store(0);
}
}
};
struct peterson_mutex_test2 : rl::test_suite<peterson_mutex_test2, 2>
{
std::atomic<int> flag0;
std::atomic<int> flag1;
std::atomic<int> turn;
rl::var<int> data;
void before()
{
flag0($) = 0;
flag1($) = 0;
turn($) = 0;
}
void thread(unsigned index)
{
if (0 == index)
{
flag0.store(1, rl::memory_order_relaxed);
turn.exchange(1, rl::memory_order_acq_rel);
while (flag1.load(rl::memory_order_acquire)
&& 1 == turn.load(rl::memory_order_relaxed))
rl::yield(1, $);
data($) = 1;
flag0.store(0, rl::memory_order_release);
}
else
{
flag1.store(1, rl::memory_order_relaxed);
turn.exchange(0, rl::memory_order_acq_rel);
while (flag0.load(rl::memory_order_acquire)
&& 0 == turn.load(rl::memory_order_relaxed))
rl::yield(1, $);
data($) = 2;
flag1.store(0, rl::memory_order_release);
}
}
};
struct peterson_mutex_test3 : rl::test_suite<peterson_mutex_test3, 2>
{
std::atomic<int> flag0;
std::atomic<int> flag1;
std::atomic<int> turn;
rl::var<int> data;
void before()
{
flag0($) = 0;
flag1($) = 0;
turn($) = 0;
}
void thread(unsigned index)
{
if (0 == index)
{
flag0.store(1, std::memory_order_relaxed);
std::atomic_thread_fence(std::memory_order_seq_cst);
turn.store(1, std::memory_order_relaxed);
std::atomic_thread_fence(std::memory_order_seq_cst);
while (flag1.load(std::memory_order_acquire)
&& 1 == turn.load(std::memory_order_relaxed));
data($) = 1;
flag0.store(0, std::memory_order_release);
}
else
{
flag1.store(1, std::memory_order_relaxed);
std::atomic_thread_fence(std::memory_order_seq_cst);
turn.store(0, std::memory_order_relaxed);
std::atomic_thread_fence(std::memory_order_seq_cst);
while (flag0.load(std::memory_order_acquire)
&& 0 == turn.load(std::memory_order_relaxed));
data($) = 2;
flag1.store(0, std::memory_order_release);
}
}
};
// FAILS WITH DATA RACE
struct peterson_mutex_test4 : rl::test_suite<peterson_mutex_test4, 2>
{
std::atomic<int> flag0;
std::atomic<int> flag1;
std::atomic<int> turn;
rl::var<int> data;
void before()
{
flag0($) = 0;
flag1($) = 0;
turn($) = 0;
}
void thread(unsigned index)
{
if (0 == index)
{
flag0.exchange(1, rl::memory_order_acq_rel);
turn.store(1, rl::memory_order_release);
while (flag1.load(rl::memory_order_acquire)
&& 1 == turn.load(rl::memory_order_acquire))
rl::yield(1, $);
data($) = 1;
flag0.store(0, rl::memory_order_release);
}
else
{
flag1.exchange(1, rl::memory_order_acq_rel);
turn.store(0, rl::memory_order_release);
while (flag0.load(rl::memory_order_acquire)
&& 0 == turn.load(rl::memory_order_relaxed))
rl::yield(1, $);
data($) = 2;
flag1.store(0, rl::memory_order_release);
}
}
};
class eventcount
{
public:
typedef unsigned state_t;
eventcount()
{
state_.store(0, std::memory_order_relaxed);
sema_ = CreateSemaphore(0, 0, LONG_MAX, 0);
}
~eventcount()
{
CloseHandle(sema_);
}
state_t prepare()
{
return state_.fetch_add(waiters_inc, std::memory_order_seq_cst);
}
void retire()
{
state_.fetch_add((state_t)-(int)waiters_inc, std::memory_order_seq_cst);
}
void wait(state_t cmp)
{
WaitForSingleObject(sema_, INFINITE);
state_t cmp0 = state_.load(std::memory_order_seq_cst);
if ((cmp & generation_mask) == (cmp0 & generation_mask))
{
state_.fetch_add((state_t)-(int)waiters_inc, std::memory_order_seq_cst);
ReleaseSemaphore(sema_, 1, 0);
SwitchToThread();
}
}
void signal()
{
std::atomic_thread_fence(std::memory_order_seq_cst);
signal_relaxed();
}
void signal_relaxed()
{
state_t cmp = state_.load(std::memory_order_seq_cst);
if (0 == (cmp & waiters_mask))
return;
for (;;)
{
state_t xchg = (cmp & ~waiters_mask) + generation_inc;
if (state_.compare_exchange_weak(cmp, xchg, std::memory_order_seq_cst))
{
ReleaseSemaphore(sema_, cmp & waiters_mask, 0);
return;
}
if (0 == (cmp & waiters_mask))
return;
}
}
private:
std::atomic<state_t> state_;
HANDLE sema_;
static state_t const waiters_inc = 1;
static state_t const waiters_mask = (1 << 20) - 1;
static state_t const generation_inc = 1 << 20;
static state_t const generation_mask = ~waiters_mask;
eventcount(eventcount const&);
eventcount& operator = (eventcount const&);
};
class eventcount_blocking
{
public:
eventcount_blocking(eventcount& ec)
: ec_(ec)
{
cmp_ = ec_.prepare();
wait_ = false;
}
void wait()
{
RL_ASSERT(false == wait_);
wait_ = true;
ec_.wait(cmp_);
}
~eventcount_blocking()
{
if (false == wait_)
ec_.retire();
}
private:
eventcount& ec_;
eventcount::state_t cmp_;
bool wait_;
eventcount_blocking(eventcount_blocking const&);
eventcount_blocking& operator = (eventcount_blocking const&);
};
struct signaling_test : rl::test_suite<signaling_test, 6>
{
//rl::HANDLE var_wait_for_items;
//rl::CRITICAL_SECTION mtx_items_avail;
//std::atomic<unsigned> n_waiting_consumers;
//rl::var<unsigned> consumer_wait_generation;
//rl::var<unsigned> n_consumers_to_wakeup;
eventcount ec_;
static int const max_queue_length = 4;
int queue [max_queue_length];
int queue_head;
int queue_tail;
int queue_head_data;
int queue_tail_data;
void before()
{
//var_wait_for_items = rl::CreateEvent(0, 1, 0, 0, $);
//rl::InitializeCriticalSection(&mtx_items_avail, $);
//n_waiting_consumers($) = 0;
//consumer_wait_generation($) = 0;
//n_consumers_to_wakeup($) = 0;
for (int i = 0; i != max_queue_length; ++i)
queue[i] = 0;
queue_head = 0;
queue_tail = 0;
queue_head_data = 0;
queue_tail_data = 0;
}
void after()
{
//rl::CloseHandle(var_wait_for_items, $);
//rl::DeleteCriticalSection(&mtx_items_avail, $);
}
struct enqueue_desc
{
int pos;
void output(std::ostream& s) const
{
s << "enqueue " << pos;
}
};
void enqueue()
{
queue[queue_head++] = ++queue_head_data;
RL_HIST_IMPL(rl::ctx(), $, enqueue_desc) {queue_head - 1} RL_HIST_END();
signal();
}
void dequeue()
{
int my_pos = queue_tail++;
for (;;)
{
if (queue[my_pos])
{
RL_ASSERT(queue[my_pos] == my_pos + 1);
return;
}
wait(my_pos);
}
}
void signal()
{
ec_.signal();
/*
std::atomic_thread_fence($)(std::memory_order_seq_cst);
if (n_waiting_consumers($).load(std::memory_order_relaxed))
{
rl::EnterCriticalSection(&mtx_items_avail, $);
if (n_waiting_consumers($).load(std::memory_order_relaxed) > 0)
{
consumer_wait_generation($) += 1;
//RL_ASSERT(n_consumers_to_wakeup($) == 0);
n_consumers_to_wakeup($) = n_waiting_consumers($).load(std::memory_order_relaxed);
rl::SetEvent(var_wait_for_items, $);
}
rl::LeaveCriticalSection(&mtx_items_avail, $);
}
*/
}
void wait(int my_pos)
{
eventcount_blocking block (ec_);
if (queue[my_pos])
return;
block.wait();
/*
rl::EnterCriticalSection(&mtx_items_avail, $);
n_waiting_consumers($).store(n_waiting_consumers($).load(std::memory_order_relaxed) + 1, std::memory_order_relaxed);
std::atomic_thread_fence($)(std::memory_order_seq_cst);
while (0 == queue[my_pos])
{
unsigned my_generation = consumer_wait_generation($);
for (;;)
{
rl::LeaveCriticalSection(&mtx_items_avail, $);
rl::WaitForSingleObject(var_wait_for_items, rl::RL_INFINITE, $);
rl::EnterCriticalSection(&mtx_items_avail, $);
if (n_consumers_to_wakeup($) > 0 && consumer_wait_generation($) != my_generation)
break;
}
if (--n_consumers_to_wakeup($) == 0)
rl::ResetEvent(var_wait_for_items, $);
}
n_waiting_consumers($).store(n_waiting_consumers($).load(std::memory_order_relaxed) - 1, std::memory_order_relaxed);
rl::LeaveCriticalSection(&mtx_items_avail, $);
*/
}
void thread(unsigned index)
{
if (index < rl::test_suite<signaling_test, 6>::params::thread_count/2+1)
{
enqueue();
}
else
{
dequeue();
}
}
};
int main()
{
rl::test_params p;
//p.search_type = rl::fair_context_bound_scheduler_type;
p.search_type = rl::sched_bound;
//p.context_bound = 1;
//p.execution_depth_limit = 100;
//p.iteration_count = 5000;
//p.initial_state = "280572";
//rl::simulate<signaling_test>(p);
rl::simulate<peterson_mutex_test>();
rl::simulate<peterson_mutex_test2>(p);
rl::simulate<peterson_mutex_test3>();
rl::simulate<peterson_mutex_test4>(p);
}
@@ -0,0 +1,2 @@
#include "stdafx.h"
@@ -0,0 +1,14 @@
#pragma once
#ifdef NDEBUG
# define _SECURE_SCL 0
#endif
#define RL_MSVC_OUTPUT
//#define RL_DEBUGBREAK_ON_FAILURE
#include "../../relacy/pch.hpp"
#include "../../relacy/relacy_std.hpp"
@@ -0,0 +1,20 @@
Microsoft Visual Studio Solution File, Format Version 9.00
# Visual Studio 2005
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "proxy_collector", "proxy_collector.vcproj", "{31994C0C-3BAD-4F25-8BC8-3206FF349B29}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Win32 = Debug|Win32
Release|Win32 = Release|Win32
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{31994C0C-3BAD-4F25-8BC8-3206FF349B29}.Debug|Win32.ActiveCfg = Debug|Win32
{31994C0C-3BAD-4F25-8BC8-3206FF349B29}.Debug|Win32.Build.0 = Debug|Win32
{31994C0C-3BAD-4F25-8BC8-3206FF349B29}.Release|Win32.ActiveCfg = Release|Win32
{31994C0C-3BAD-4F25-8BC8-3206FF349B29}.Release|Win32.Build.0 = Release|Win32
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
EndGlobal
@@ -0,0 +1,291 @@
<?xml version="1.0" encoding="windows-1251"?>
<VisualStudioProject
ProjectType="Visual C++"
Version="8,00"
Name="proxy_collector"
ProjectGUID="{31994C0C-3BAD-4F25-8BC8-3206FF349B29}"
RootNamespace="ref_counting"
Keyword="Win32Proj"
>
<Platforms>
<Platform
Name="Win32"
/>
</Platforms>
<ToolFiles>
</ToolFiles>
<Configurations>
<Configuration
Name="Debug|Win32"
OutputDirectory="$(SolutionDir)$(ConfigurationName)"
IntermediateDirectory="$(ConfigurationName)"
ConfigurationType="1"
CharacterSet="1"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
/>
<Tool
Name="VCCLCompilerTool"
Optimization="0"
PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE"
MinimalRebuild="true"
BasicRuntimeChecks="3"
RuntimeLibrary="3"
UsePrecompiledHeader="2"
WarningLevel="4"
DebugInformationFormat="4"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
LinkIncremental="2"
GenerateDebugInformation="true"
SubSystem="1"
TargetMachine="1"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCWebDeploymentTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
<Configuration
Name="Release|Win32"
OutputDirectory="$(SolutionDir)$(ConfigurationName)"
IntermediateDirectory="$(ConfigurationName)"
ConfigurationType="1"
CharacterSet="1"
WholeProgramOptimization="1"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
/>
<Tool
Name="VCCLCompilerTool"
InlineFunctionExpansion="2"
EnableIntrinsicFunctions="true"
FavorSizeOrSpeed="1"
OmitFramePointers="true"
EnableFiberSafeOptimizations="true"
PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE"
RuntimeLibrary="2"
BufferSecurityCheck="false"
EnableEnhancedInstructionSet="2"
UsePrecompiledHeader="2"
WarningLevel="4"
DebugInformationFormat="3"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
LinkIncremental="1"
GenerateDebugInformation="true"
SubSystem="1"
OptimizeReferences="2"
EnableCOMDATFolding="2"
TargetMachine="1"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCWebDeploymentTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
<Configuration
Name="Profile|Win32"
OutputDirectory="$(SolutionDir)$(ConfigurationName)"
IntermediateDirectory="$(ConfigurationName)"
ConfigurationType="1"
CharacterSet="1"
WholeProgramOptimization="0"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
/>
<Tool
Name="VCCLCompilerTool"
AdditionalOptions="/Ob0"
EnableIntrinsicFunctions="true"
FavorSizeOrSpeed="1"
OmitFramePointers="true"
EnableFiberSafeOptimizations="true"
WholeProgramOptimization="false"
PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE"
RuntimeLibrary="2"
BufferSecurityCheck="false"
EnableEnhancedInstructionSet="2"
UsePrecompiledHeader="2"
WarningLevel="4"
Detect64BitPortabilityProblems="true"
DebugInformationFormat="3"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
LinkIncremental="1"
GenerateDebugInformation="true"
SubSystem="1"
OptimizeReferences="2"
EnableCOMDATFolding="2"
TargetMachine="1"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCWebDeploymentTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
</Configurations>
<References>
</References>
<Files>
<File
RelativePath="..\proxy_collector.cpp"
>
</File>
<File
RelativePath="..\stdafx.cpp"
>
<FileConfiguration
Name="Debug|Win32"
>
<Tool
Name="VCCLCompilerTool"
UsePrecompiledHeader="1"
/>
</FileConfiguration>
<FileConfiguration
Name="Release|Win32"
>
<Tool
Name="VCCLCompilerTool"
UsePrecompiledHeader="1"
/>
</FileConfiguration>
</File>
<File
RelativePath="..\stdafx.h"
>
</File>
</Files>
<Globals>
</Globals>
</VisualStudioProject>
@@ -0,0 +1,20 @@
Microsoft Visual Studio Solution File, Format Version 10.00
# Visual Studio 2008
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "proxy_collector", "proxy_collector.vcproj", "{31994C0C-3BAD-4F25-8BC8-3206FF349B29}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Win32 = Debug|Win32
Release|Win32 = Release|Win32
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{31994C0C-3BAD-4F25-8BC8-3206FF349B29}.Debug|Win32.ActiveCfg = Debug|Win32
{31994C0C-3BAD-4F25-8BC8-3206FF349B29}.Debug|Win32.Build.0 = Debug|Win32
{31994C0C-3BAD-4F25-8BC8-3206FF349B29}.Release|Win32.ActiveCfg = Release|Win32
{31994C0C-3BAD-4F25-8BC8-3206FF349B29}.Release|Win32.Build.0 = Release|Win32
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
EndGlobal
@@ -0,0 +1,299 @@
<?xml version="1.0" encoding="windows-1251"?>
<VisualStudioProject
ProjectType="Visual C++"
Version="9,00"
Name="proxy_collector"
ProjectGUID="{31994C0C-3BAD-4F25-8BC8-3206FF349B29}"
RootNamespace="ref_counting"
Keyword="Win32Proj"
>
<Platforms>
<Platform
Name="Win32"
/>
</Platforms>
<ToolFiles>
</ToolFiles>
<Configurations>
<Configuration
Name="Debug|Win32"
OutputDirectory="$(SolutionDir)$(ConfigurationName)"
IntermediateDirectory="$(ConfigurationName)"
ConfigurationType="1"
CharacterSet="1"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
/>
<Tool
Name="VCCLCompilerTool"
Optimization="0"
PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE"
MinimalRebuild="true"
BasicRuntimeChecks="3"
RuntimeLibrary="3"
UsePrecompiledHeader="2"
WarningLevel="4"
DebugInformationFormat="4"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
LinkIncremental="2"
GenerateDebugInformation="true"
SubSystem="1"
TargetMachine="1"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCWebDeploymentTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
<Configuration
Name="Release|Win32"
OutputDirectory="$(SolutionDir)$(ConfigurationName)"
IntermediateDirectory="$(ConfigurationName)"
ConfigurationType="1"
CharacterSet="1"
WholeProgramOptimization="1"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
/>
<Tool
Name="VCCLCompilerTool"
InlineFunctionExpansion="2"
EnableIntrinsicFunctions="true"
FavorSizeOrSpeed="1"
OmitFramePointers="true"
EnableFiberSafeOptimizations="true"
PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE"
RuntimeLibrary="2"
BufferSecurityCheck="false"
EnableEnhancedInstructionSet="2"
UsePrecompiledHeader="2"
WarningLevel="4"
DebugInformationFormat="3"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
LinkIncremental="1"
GenerateDebugInformation="true"
SubSystem="1"
OptimizeReferences="2"
EnableCOMDATFolding="2"
TargetMachine="1"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCWebDeploymentTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
<Configuration
Name="Profile|Win32"
OutputDirectory="$(SolutionDir)$(ConfigurationName)"
IntermediateDirectory="$(ConfigurationName)"
ConfigurationType="1"
CharacterSet="1"
WholeProgramOptimization="0"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
/>
<Tool
Name="VCCLCompilerTool"
AdditionalOptions="/Ob0"
EnableIntrinsicFunctions="true"
FavorSizeOrSpeed="1"
OmitFramePointers="true"
EnableFiberSafeOptimizations="true"
WholeProgramOptimization="false"
PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE"
RuntimeLibrary="2"
BufferSecurityCheck="false"
EnableEnhancedInstructionSet="2"
UsePrecompiledHeader="2"
WarningLevel="4"
Detect64BitPortabilityProblems="true"
DebugInformationFormat="3"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
LinkIncremental="1"
GenerateDebugInformation="true"
SubSystem="1"
OptimizeReferences="2"
EnableCOMDATFolding="2"
TargetMachine="1"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCWebDeploymentTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
</Configurations>
<References>
</References>
<Files>
<File
RelativePath="..\original.hpp"
>
</File>
<File
RelativePath="..\proxy_collector.cpp"
>
</File>
<File
RelativePath="..\rtl.hpp"
>
</File>
<File
RelativePath="..\stdafx.cpp"
>
<FileConfiguration
Name="Debug|Win32"
>
<Tool
Name="VCCLCompilerTool"
UsePrecompiledHeader="1"
/>
</FileConfiguration>
<FileConfiguration
Name="Release|Win32"
>
<Tool
Name="VCCLCompilerTool"
UsePrecompiledHeader="1"
/>
</FileConfiguration>
</File>
<File
RelativePath="..\stdafx.h"
>
</File>
</Files>
<Globals>
</Globals>
</VisualStudioProject>
@@ -0,0 +1,318 @@
#include "stdafx.h"
#include <stdint.h>
#include "../../relacy/relacy_std.hpp"
struct pc_sys_anchor;
struct pc_region;
struct pc_master;
typedef pc_region pc_node;
typedef void (pc_fp_dtor) (pc_region*);
struct pc_sys_anchor
{
int refcnt;
pc_region* region;
pc_sys_anchor()
{
}
pc_sys_anchor(int rc, pc_region* r = 0)
{
refcnt = rc;
region = r;
}
bool operator == (pc_sys_anchor const& right) const
{
return refcnt == right.refcnt
&& region == right.region;
}
pc_sys_anchor operator + (pc_sys_anchor const& right) const
{
pc_sys_anchor res;
res.refcnt = refcnt + right.refcnt;
res.region = (pc_region*)((intptr_t)region + (intptr_t)right.region);
return res;
}
pc_sys_anchor operator - (pc_sys_anchor const& right) const
{
pc_sys_anchor res;
res.refcnt = refcnt - right.refcnt;
res.region = (pc_region*)((intptr_t)region - (intptr_t)right.region);
return res;
}
};
std::ostream& operator << (std::ostream& s, pc_sys_anchor const& right)
{
return s << "{" << right.refcnt << "," << right.region << "}";
}
struct pc_region
{
std::atomic<pc_sys_anchor> next;
std::atomic<pc_region*> defer;
pc_region()
{
next($) = pc_sys_anchor(0, 0);
defer($) = 0;
}
void link(pc_region* next)
{
defer.store(next, rl::memory_order_relaxed);
}
void defer_node(pc_region* node)
{
pc_region* region = defer.exchange(node, rl::memory_order_release);
node->defer.store(region, rl::memory_order_relaxed);
}
};
struct pc_master
{
std::atomic<pc_sys_anchor> head;
pc_region stub_region;
pc_fp_dtor* fp_dtor;
pc_master(pc_fp_dtor* const dtor)
{
pc_sys_anchor src (0, &stub_region);
head.store(src, rl::memory_order_relaxed);
fp_dtor = dtor;
}
pc_region* acquire()
{
pc_sys_anchor cmp (head.load(rl::memory_order_relaxed));
pc_sys_anchor xchg;
do
{
xchg.refcnt = cmp.refcnt + 2;
xchg.region = cmp.region;
}
while (false == head.compare_exchange_weak(cmp, xchg, rl::memory_order_acquire));
return cmp.region;
}
void release(pc_region* region)
{
pc_sys_anchor prev = region->next.fetch_sub(2, rl::memory_order_acq_rel);
if (prev.refcnt == 3)
sys_dtor(region);
}
void mutate(pc_region* node)
{
pc_sys_anchor src (2, 0);
node->next.store(src, rl::memory_order_relaxed);
pc_sys_anchor xchg (0, node);
pc_sys_anchor cmp = head.load(rl::memory_order_relaxed);
while (false == head.compare_exchange_weak(cmp, xchg, std::memory_order_acq_rel));
pc_sys_anchor cmp2 = cmp.region->next.load(rl::memory_order_relaxed);
pc_sys_anchor xchg2;
do
{
xchg2 = pc_sys_anchor(cmp2.refcnt, node);
}
while (false == cmp.region->next.compare_exchange_weak(cmp2, xchg2, rl::memory_order_release));
pc_sys_anchor prev = cmp.region->next.fetch_add(cmp.refcnt + 1, rl::memory_order_acq_rel);
if (prev.refcnt == -cmp.refcnt)
sys_dtor(cmp.region);
}
void sys_dtor(pc_region* region)
{
int reset = 0;
pc_region* head = region;
pc_region* tail = region;
pc_sys_anchor nx = region->next.load(rl::memory_order_relaxed);
pc_region* next = nx.region;
while (next)
{
pc_sys_anchor prev = next->next.fetch_sub(2, rl::memory_order_acq_rel);
if (prev.refcnt != 3)
break;
tail = next;
nx = next->next.load(rl::memory_order_relaxed);
next = nx.region;
}
nx = tail->next.load(rl::memory_order_relaxed);
nx.region = 0;
tail->next.store(nx, rl::memory_order_relaxed);
while (head)
{
nx = head->next.load(rl::memory_order_relaxed);
pc_region* const next = nx.region;
pc_region* defer = head->defer.load(rl::memory_order_relaxed);
nx = head->next.load(rl::memory_order_relaxed);
RL_ASSERT(nx.refcnt == 1);
if (head != &stub_region)
{
head->defer.store(defer, rl::memory_order_relaxed);
defer = head;
}
else
{
reset = 1;
}
while (defer)
{
pc_region* const next = defer->defer.load(rl::memory_order_relaxed);
fp_dtor(defer);
defer = next;
}
head = next;
}
if (reset)
{
stub_region.defer.store(0, rl::memory_order_relaxed);
mutate(&stub_region);
}
}
};
struct foo_node
{
pc_node pcn;
std::atomic<foo_node*> next;
rl::var<int> data;
};
void foo_node_dtor(pc_node* pcn)
{
// yes, very fragile
foo_node* const n = (foo_node*)pcn;
delete n;
}
struct foo_list
{
std::atomic<foo_node*> head;
pc_master pc;
foo_list()
: head(0)
, pc(foo_node_dtor)
{
}
};
struct proxy_collector_test : rl::test_suite<proxy_collector_test, 4>
{
foo_list m_list;
void before()
{
m_list.head($) = 0;
}
void after()
{
foo_node* node = new foo_node;
m_list.pc.mutate(&node->pcn);
}
void thread(unsigned index)
{
if (index < 2)
{
pc_region* pcr = m_list.pc.acquire();
for (int i = 0; i != 4; ++i)
{
foo_node* node = m_list.head.load(rl::memory_order_acquire);
while (node)
{
foo_node* const next = node->next.load(rl::memory_order_acquire);
intptr_t volatile data = node->data($);
(void)data;
node = next;
}
if (2 == i)
{
m_list.pc.release(pcr);
pcr = m_list.pc.acquire();
}
}
m_list.pc.release(pcr);
}
else
{
pc_region* pcr = m_list.pc.acquire();
for (int i = 0; i != 4; ++i)
{
if (0 == (i % 2))
{
foo_node* node = new foo_node;
node->data($) = 1;
foo_node* cmp = m_list.head.load(rl::memory_order_relaxed);
do
{
node->next.store(cmp, rl::memory_order_relaxed);
}
while (false == m_list.head.compare_exchange_weak(cmp, node, rl::memory_order_release));
}
else
{
foo_node* node = m_list.head.load(rl::memory_order_acquire);
foo_node* next;
do
{
if (0 == node)
break;
next = node->next.load(rl::memory_order_relaxed);
}
while (false == m_list.head.compare_exchange_weak(node, next, rl::memory_order_acquire));
if (node)
{
//if (1 == i)
{
m_list.pc.mutate(&node->pcn);
}
//else
//{
// pcr->defer_node(&node->pcn);
//}
}
}
if (i % 2)
{
m_list.pc.release(pcr);
pcr = m_list.pc.acquire();
}
}
m_list.pc.release(pcr);
}
}
};
int main()
{
rl::test_params params;
params.iteration_count = 1000;
rl::simulate<proxy_collector_test>(params);
}
@@ -0,0 +1,2 @@
#include "stdafx.h"
@@ -0,0 +1,11 @@
#pragma once
#ifdef NDEBUG
# define _SECURE_SCL 0
#endif
#include "../../relacy/pch.hpp"
#include <sstream>
@@ -0,0 +1,20 @@
Microsoft Visual Studio Solution File, Format Version 9.00
# Visual Studio 2005
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ref_counting", "ref_counting.vcproj", "{31994C0C-3BAD-4F25-8BC8-3206FF349B28}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Win32 = Debug|Win32
Release|Win32 = Release|Win32
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{31994C0C-3BAD-4F25-8BC8-3206FF349B28}.Debug|Win32.ActiveCfg = Debug|Win32
{31994C0C-3BAD-4F25-8BC8-3206FF349B28}.Debug|Win32.Build.0 = Debug|Win32
{31994C0C-3BAD-4F25-8BC8-3206FF349B28}.Release|Win32.ActiveCfg = Release|Win32
{31994C0C-3BAD-4F25-8BC8-3206FF349B28}.Release|Win32.Build.0 = Release|Win32
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
EndGlobal
@@ -0,0 +1,208 @@
<?xml version="1.0" encoding="windows-1251"?>
<VisualStudioProject
ProjectType="Visual C++"
Version="8,00"
Name="ref_counting"
ProjectGUID="{31994C0C-3BAD-4F25-8BC8-3206FF349B28}"
RootNamespace="ref_counting"
Keyword="Win32Proj"
>
<Platforms>
<Platform
Name="Win32"
/>
</Platforms>
<ToolFiles>
</ToolFiles>
<Configurations>
<Configuration
Name="Debug|Win32"
OutputDirectory="$(SolutionDir)$(ConfigurationName)"
IntermediateDirectory="$(ConfigurationName)"
ConfigurationType="1"
CharacterSet="1"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
/>
<Tool
Name="VCCLCompilerTool"
Optimization="0"
PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE"
MinimalRebuild="true"
BasicRuntimeChecks="3"
RuntimeLibrary="3"
UsePrecompiledHeader="2"
WarningLevel="4"
DebugInformationFormat="4"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
LinkIncremental="2"
GenerateDebugInformation="true"
SubSystem="1"
TargetMachine="1"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCWebDeploymentTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
<Configuration
Name="Release|Win32"
OutputDirectory="$(SolutionDir)$(ConfigurationName)"
IntermediateDirectory="$(ConfigurationName)"
ConfigurationType="1"
CharacterSet="1"
WholeProgramOptimization="1"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
/>
<Tool
Name="VCCLCompilerTool"
InlineFunctionExpansion="2"
EnableIntrinsicFunctions="true"
FavorSizeOrSpeed="1"
OmitFramePointers="true"
EnableFiberSafeOptimizations="true"
PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE"
RuntimeLibrary="2"
BufferSecurityCheck="false"
EnableEnhancedInstructionSet="2"
UsePrecompiledHeader="2"
WarningLevel="4"
DebugInformationFormat="3"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
LinkIncremental="1"
GenerateDebugInformation="true"
SubSystem="1"
OptimizeReferences="2"
EnableCOMDATFolding="2"
TargetMachine="1"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCWebDeploymentTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
</Configurations>
<References>
</References>
<Files>
<File
RelativePath="..\ref_counting.cpp"
>
</File>
<File
RelativePath="..\stdafx.cpp"
>
<FileConfiguration
Name="Debug|Win32"
>
<Tool
Name="VCCLCompilerTool"
UsePrecompiledHeader="1"
/>
</FileConfiguration>
<FileConfiguration
Name="Release|Win32"
>
<Tool
Name="VCCLCompilerTool"
UsePrecompiledHeader="1"
/>
</FileConfiguration>
</File>
<File
RelativePath="..\stdafx.h"
>
</File>
</Files>
<Globals>
</Globals>
</VisualStudioProject>
@@ -0,0 +1,20 @@
Microsoft Visual Studio Solution File, Format Version 10.00
# Visual Studio 2008
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ref_counting", "ref_counting.vcproj", "{31994C0C-3BAD-4F25-8BC8-3206FF349B28}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Win32 = Debug|Win32
Release|Win32 = Release|Win32
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{31994C0C-3BAD-4F25-8BC8-3206FF349B28}.Debug|Win32.ActiveCfg = Debug|Win32
{31994C0C-3BAD-4F25-8BC8-3206FF349B28}.Debug|Win32.Build.0 = Debug|Win32
{31994C0C-3BAD-4F25-8BC8-3206FF349B28}.Release|Win32.ActiveCfg = Release|Win32
{31994C0C-3BAD-4F25-8BC8-3206FF349B28}.Release|Win32.Build.0 = Release|Win32
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
EndGlobal
@@ -0,0 +1,207 @@
<?xml version="1.0" encoding="windows-1251"?>
<VisualStudioProject
ProjectType="Visual C++"
Version="9,00"
Name="ref_counting"
ProjectGUID="{31994C0C-3BAD-4F25-8BC8-3206FF349B28}"
RootNamespace="ref_counting"
Keyword="Win32Proj"
TargetFrameworkVersion="131072"
>
<Platforms>
<Platform
Name="Win32"
/>
</Platforms>
<ToolFiles>
</ToolFiles>
<Configurations>
<Configuration
Name="Debug|Win32"
OutputDirectory="$(SolutionDir)$(ConfigurationName)"
IntermediateDirectory="$(ConfigurationName)"
ConfigurationType="1"
CharacterSet="1"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
/>
<Tool
Name="VCCLCompilerTool"
Optimization="0"
PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE"
MinimalRebuild="true"
BasicRuntimeChecks="3"
RuntimeLibrary="3"
UsePrecompiledHeader="2"
WarningLevel="4"
DebugInformationFormat="4"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
LinkIncremental="2"
GenerateDebugInformation="true"
SubSystem="1"
RandomizedBaseAddress="1"
DataExecutionPrevention="0"
TargetMachine="1"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
<Configuration
Name="Release|Win32"
OutputDirectory="$(SolutionDir)$(ConfigurationName)"
IntermediateDirectory="$(ConfigurationName)"
ConfigurationType="1"
CharacterSet="1"
WholeProgramOptimization="1"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
/>
<Tool
Name="VCCLCompilerTool"
InlineFunctionExpansion="2"
EnableIntrinsicFunctions="true"
FavorSizeOrSpeed="1"
OmitFramePointers="true"
EnableFiberSafeOptimizations="true"
PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE"
RuntimeLibrary="2"
BufferSecurityCheck="false"
EnableEnhancedInstructionSet="2"
UsePrecompiledHeader="2"
WarningLevel="4"
DebugInformationFormat="3"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
LinkIncremental="1"
GenerateDebugInformation="true"
SubSystem="1"
OptimizeReferences="2"
EnableCOMDATFolding="2"
RandomizedBaseAddress="1"
DataExecutionPrevention="0"
TargetMachine="1"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
</Configurations>
<References>
</References>
<Files>
<File
RelativePath="..\ref_counting.cpp"
>
</File>
<File
RelativePath="..\stdafx.cpp"
>
<FileConfiguration
Name="Debug|Win32"
>
<Tool
Name="VCCLCompilerTool"
UsePrecompiledHeader="1"
/>
</FileConfiguration>
<FileConfiguration
Name="Release|Win32"
>
<Tool
Name="VCCLCompilerTool"
UsePrecompiledHeader="1"
/>
</FileConfiguration>
</File>
<File
RelativePath="..\stdafx.h"
>
</File>
</Files>
<Globals>
</Globals>
</VisualStudioProject>
@@ -0,0 +1,269 @@
#include "stdafx.h"
#include "../../relacy/relacy_std.hpp"
struct rc_object
{
std::atomic<int> rc;
rl::var<int> data;
void acquire()
{
rc.fetch_add(1, rl::memory_order_acquire);
}
void release()
{
if (1 == rc.fetch_sub(1, rl::memory_order_release))
{
rc.load(rl::memory_order_acquire);
data($) = 0;
delete this;
}
}
rc_object(int data)
: rc(1)
, data(data)
{
}
};
void post_to_channel(rl::atomic<rc_object*>& ch, rc_object* obj)
{
obj->acquire();
rl::backoff b;
for (;;)
{
rc_object* cmp = 0;
if (ch.compare_exchange_weak(cmp, obj, rl::memory_order_release))
break;
b.yield($);
}
}
rc_object* get_from_channel(rl::atomic<rc_object*>& ch)
{
return ch.exchange(0, rl::memory_order_acquire);
}
struct ref_counting_test : rl::test_suite<ref_counting_test, 2>
{
std::atomic<rc_object*> channel;
void before()
{
channel($) = 0;
}
void thread(unsigned index)
{
if (0 == index)
{
rc_object* obj = new rc_object (rand());
post_to_channel(channel, obj);
int data = obj->data($);
(void)data;
obj->release();
}
else if (1 == index)
{
rl::backoff b;
for (;;)
{
rc_object* obj = get_from_channel(channel);
if (obj)
{
int data = obj->data($);
(void)data;
obj->release();
break;
}
else
{
b.yield($);
}
}
}
}
};
struct ref_counting_test2 : rl::test_suite<ref_counting_test2, 3>
{
std::atomic<rc_object*> channel01;
std::atomic<rc_object*> channel02;
std::atomic<rc_object*> channel12;
std::atomic<rc_object*> channel21;
void before()
{
channel01($) = 0;
channel02($) = 0;
channel12($) = 0;
channel21($) = 0;
}
void thread(unsigned index)
{
if (0 == index)
{
{
rc_object* obj1 = new rc_object (rand());
post_to_channel(channel01, obj1);
volatile int data = obj1->data($);
(void)data;
obj1->release();
}
{
rc_object* obj2 = new rc_object (rand());
post_to_channel(channel02, obj2);
volatile int data = obj2->data($);
(void)data;
obj2->release();
}
}
else if (1 == index)
{
rl::backoff b;
bool ch0 = false;
bool ch2 = false;
while (!ch0 || !ch2)
{
{
rc_object* obj = get_from_channel(channel01);
if (obj)
{
post_to_channel(channel12, obj);
volatile int data = obj->data($);
(void)data;
obj->release();
ch0 = true;
}
else
{
b.yield($);
}
}
{
rc_object* obj = get_from_channel(channel21);
if (obj)
{
volatile int data = obj->data($);
(void)data;
obj->release();
ch2 = true;
}
else
{
b.yield($);
}
}
}
}
else
{
rl::backoff b;
bool ch0 = false;
bool ch1 = false;
while (!ch0 || !ch1)
{
{
rc_object* obj = get_from_channel(channel02);
if (obj)
{
post_to_channel(channel21, obj);
volatile int data = obj->data($);
(void)data;
obj->release();
ch0 = true;
}
else
{
b.yield($);
}
}
{
rc_object* obj = get_from_channel(channel12);
if (obj)
{
volatile int data = obj->data($);
(void)data;
obj->release();
ch1 = true;
}
else
{
b.yield($);
}
}
}
}
}
};
struct ref_counting_test3 : rl::test_suite<ref_counting_test3, 2>
{
std::atomic<rc_object*> channel;
void before()
{
channel($) = 0;
}
void thread(unsigned index)
{
if (0 == index)
{
rc_object* obj = new rc_object (rand());
post_to_channel(channel, obj);
volatile int data = obj->data($);
(void)data;
obj->release();
}
else if (1 == index)
{
rl::backoff b;
rc_object* obj = 0;
for (;;)
{
obj = get_from_channel(channel);
if (obj)
break;
else
b.yield($);
}
obj->acquire();
obj->release();
//volatile int data = obj->data($);
//(void)data;
obj->release();
}
}
};
int main()
{
rl::test_params params;
params.context_bound = 2;
params.iteration_count = 10000;
rl::simulate<ref_counting_test>(params);
std::cout << "count: " << params.stop_iteration << std::endl;
}
@@ -0,0 +1,2 @@
#include "stdafx.h"
@@ -0,0 +1,8 @@
#pragma once
#ifdef NDEBUG
# define _SECURE_SCL 0
#endif
#include "../../relacy/pch.hpp"
@@ -0,0 +1,11 @@
TARGET=smr
SRC=smr.cpp
HEADERS=stdafx.h
all: ${TARGET}
${TARGET}: Makefile ${SRC} ${HEADERS}
g++ ${SRC} -O3 -g -o ${TARGET}
clean:
rm ${TARGET}
@@ -0,0 +1,20 @@
Microsoft Visual Studio Solution File, Format Version 9.00
# Visual Studio 2005
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "smr", "smr.vcproj", "{BC168133-5E3D-4691-BA15-8E0FD61DFDB5}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Win32 = Debug|Win32
Release|Win32 = Release|Win32
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{BC168133-5E3D-4691-BA15-8E0FD61DFDB5}.Debug|Win32.ActiveCfg = Debug|Win32
{BC168133-5E3D-4691-BA15-8E0FD61DFDB5}.Debug|Win32.Build.0 = Debug|Win32
{BC168133-5E3D-4691-BA15-8E0FD61DFDB5}.Release|Win32.ActiveCfg = Release|Win32
{BC168133-5E3D-4691-BA15-8E0FD61DFDB5}.Release|Win32.Build.0 = Release|Win32
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
EndGlobal
@@ -0,0 +1,199 @@
<?xml version="1.0" encoding="windows-1251"?>
<VisualStudioProject
ProjectType="Visual C++"
Version="8,00"
Name="smr"
ProjectGUID="{BC168133-5E3D-4691-BA15-8E0FD61DFDB5}"
RootNamespace="smr"
Keyword="Win32Proj"
TargetFrameworkVersion="196613"
>
<Platforms>
<Platform
Name="Win32"
/>
</Platforms>
<ToolFiles>
</ToolFiles>
<Configurations>
<Configuration
Name="Debug|Win32"
OutputDirectory="$(SolutionDir)$(ConfigurationName)"
IntermediateDirectory="$(ConfigurationName)"
ConfigurationType="1"
CharacterSet="1"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
/>
<Tool
Name="VCCLCompilerTool"
Optimization="0"
PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE"
MinimalRebuild="true"
BasicRuntimeChecks="3"
RuntimeLibrary="3"
UsePrecompiledHeader="2"
WarningLevel="3"
DebugInformationFormat="4"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
LinkIncremental="2"
GenerateDebugInformation="true"
SubSystem="1"
TargetMachine="1"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
<Configuration
Name="Release|Win32"
OutputDirectory="$(SolutionDir)$(ConfigurationName)"
IntermediateDirectory="$(ConfigurationName)"
ConfigurationType="1"
CharacterSet="1"
WholeProgramOptimization="1"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
/>
<Tool
Name="VCCLCompilerTool"
Optimization="2"
EnableIntrinsicFunctions="true"
PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE"
RuntimeLibrary="2"
EnableFunctionLevelLinking="true"
UsePrecompiledHeader="2"
WarningLevel="3"
DebugInformationFormat="3"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
LinkIncremental="1"
GenerateDebugInformation="true"
SubSystem="1"
OptimizeReferences="2"
EnableCOMDATFolding="2"
TargetMachine="1"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
</Configurations>
<References>
</References>
<Files>
<File
RelativePath="..\smr.cpp"
>
</File>
<File
RelativePath="..\stdafx.cpp"
>
<FileConfiguration
Name="Debug|Win32"
>
<Tool
Name="VCCLCompilerTool"
UsePrecompiledHeader="1"
/>
</FileConfiguration>
<FileConfiguration
Name="Release|Win32"
>
<Tool
Name="VCCLCompilerTool"
UsePrecompiledHeader="1"
/>
</FileConfiguration>
</File>
<File
RelativePath="..\stdafx.h"
>
</File>
</Files>
<Globals>
</Globals>
</VisualStudioProject>
@@ -0,0 +1,20 @@
Microsoft Visual Studio Solution File, Format Version 10.00
# Visual Studio 2008
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "smr", "smr.vcproj", "{BC168133-5E3D-4691-BA15-8E0FD61DFDB5}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Win32 = Debug|Win32
Release|Win32 = Release|Win32
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{BC168133-5E3D-4691-BA15-8E0FD61DFDB5}.Debug|Win32.ActiveCfg = Debug|Win32
{BC168133-5E3D-4691-BA15-8E0FD61DFDB5}.Debug|Win32.Build.0 = Debug|Win32
{BC168133-5E3D-4691-BA15-8E0FD61DFDB5}.Release|Win32.ActiveCfg = Release|Win32
{BC168133-5E3D-4691-BA15-8E0FD61DFDB5}.Release|Win32.Build.0 = Release|Win32
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
EndGlobal
@@ -0,0 +1,199 @@
<?xml version="1.0" encoding="windows-1251"?>
<VisualStudioProject
ProjectType="Visual C++"
Version="9,00"
Name="smr"
ProjectGUID="{BC168133-5E3D-4691-BA15-8E0FD61DFDB5}"
RootNamespace="smr"
Keyword="Win32Proj"
TargetFrameworkVersion="196613"
>
<Platforms>
<Platform
Name="Win32"
/>
</Platforms>
<ToolFiles>
</ToolFiles>
<Configurations>
<Configuration
Name="Debug|Win32"
OutputDirectory="$(SolutionDir)$(ConfigurationName)"
IntermediateDirectory="$(ConfigurationName)"
ConfigurationType="1"
CharacterSet="1"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
/>
<Tool
Name="VCCLCompilerTool"
Optimization="0"
PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE"
MinimalRebuild="true"
BasicRuntimeChecks="3"
RuntimeLibrary="3"
UsePrecompiledHeader="2"
WarningLevel="3"
DebugInformationFormat="4"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
LinkIncremental="2"
GenerateDebugInformation="true"
SubSystem="1"
TargetMachine="1"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
<Configuration
Name="Release|Win32"
OutputDirectory="$(SolutionDir)$(ConfigurationName)"
IntermediateDirectory="$(ConfigurationName)"
ConfigurationType="1"
CharacterSet="1"
WholeProgramOptimization="1"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
/>
<Tool
Name="VCCLCompilerTool"
Optimization="2"
EnableIntrinsicFunctions="true"
PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE"
RuntimeLibrary="2"
EnableFunctionLevelLinking="true"
UsePrecompiledHeader="2"
WarningLevel="3"
DebugInformationFormat="3"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
LinkIncremental="1"
GenerateDebugInformation="true"
SubSystem="1"
OptimizeReferences="2"
EnableCOMDATFolding="2"
TargetMachine="1"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
</Configurations>
<References>
</References>
<Files>
<File
RelativePath="..\smr.cpp"
>
</File>
<File
RelativePath="..\stdafx.cpp"
>
<FileConfiguration
Name="Debug|Win32"
>
<Tool
Name="VCCLCompilerTool"
UsePrecompiledHeader="1"
/>
</FileConfiguration>
<FileConfiguration
Name="Release|Win32"
>
<Tool
Name="VCCLCompilerTool"
UsePrecompiledHeader="1"
/>
</FileConfiguration>
</File>
<File
RelativePath="..\stdafx.h"
>
</File>
</Files>
<Globals>
</Globals>
</VisualStudioProject>
@@ -0,0 +1,189 @@
#include "stdafx.h"
#include "../../relacy/relacy_std.hpp"
unsigned const thread_count = 3;
unsigned const node_count = 6;
struct smr_test : rl::test_suite<smr_test, thread_count>
{
struct node
{
std::atomic<node*> next_;
rl::var<int> data_;
};
std::atomic<node*> head_;
std::atomic<node*> hp_ [thread_count];
rl::var<node*> defer_ [thread_count][thread_count];
rl::var<int> defer_size_ [thread_count];
void before()
{
head_.store(0, std::memory_order_relaxed);
for (size_t i = 0; i != thread_count; ++i)
{
hp_[i].store(0, std::memory_order_relaxed);
VAR(defer_size_[i]) = 0;
for (size_t j = 0; j != thread_count; ++j)
VAR(defer_[i][j]) = 0;
}
}
void push(unsigned index, int data)
{
node* n = new node ();
n->VAR(data_) = data;
node* next = head_.load(std::memory_order_relaxed);
for (;;)
{
n->next_.store(next, rl::memory_order_relaxed);
if (head_.compare_exchange_weak(next, n, rl::memory_order_release))
break;
}
}
int pop(unsigned index)
{
node* n = 0;
for (;;)
{
n = smr_acquire(index, head_);
if (0 == n)
break;
node* next = n->next_.load(rl::memory_order_relaxed);
if (head_.compare_exchange_weak(n, next, rl::memory_order_acquire))
break;
smr_release(index);
}
smr_release(index);
if (n)
{
int data = n->VAR(data_);
smr_defer(index, n);
return data;
}
else
{
return 0;
}
}
void smr_pump(unsigned index)
{
node* hp [thread_count] = {};
for (size_t i = 0; i != thread_count; ++i)
{
hp[i] = hp_[i].load(std::memory_order_relaxed);
}
for (size_t i = 0; i != thread_count; ++i)
{
node* nn = VAR(defer_[index][i]);
if (nn)
{
for (size_t j = 0; j != thread_count; ++j)
{
if (nn == hp[j])
{
nn = 0;
break;
}
}
if (nn)
{
VAR(defer_[index][i]) = 0;
VAR(defer_size_[index]) -= 1;
delete nn;
}
}
}
}
void smr_defer(unsigned index, node* n)
{
std::atomic_thread_fence(std::memory_order_seq_cst);
smr_pump(index);
if (VAR(defer_size_[index]) == thread_count)
{
delete n;
}
else
{
bool found = false;
for (size_t i = 0; i != thread_count; ++i)
{
if (VAR(defer_[index][i]) == 0)
{
VAR(defer_[index][i]) = n;
found = true;
break;
}
}
RL_ASSERT(found);
VAR(defer_size_[index]) += 1;
}
}
node* smr_acquire(unsigned index, std::atomic<node*>& n)
{
node* v = 0;
for (;;)
{
v = n.load(std::memory_order_relaxed);
hp_[index].store(v, std::memory_order_relaxed);
std::atomic_thread_fence(std::memory_order_seq_cst);
node* v2 = n.load(std::memory_order_acquire);
if (v2 == v)
break;
}
return v;
}
void smr_release(unsigned index)
{
hp_[index].store(0, std::memory_order_relaxed);
}
void thread(unsigned index)
{
for (unsigned i = 0; i != node_count; ++i)
{
push(index, index * thread_count + i + 1);
}
for (unsigned i = 0; i != node_count; ++i)
{
int data = pop(index);
RL_ASSERT(0 != data);
}
}
void after()
{
for (unsigned i = 0; i != ::thread_count; ++i)
{
smr_pump(i);
}
}
};
int main()
{
rl::test_params p;
//p.collect_history = true;
//p.output_history = true;
//p.initial_state = "991172";
p.iteration_count = 1000;
rl::simulate<smr_test>(p);
}
@@ -0,0 +1,2 @@
#include "stdafx.h"
@@ -0,0 +1,10 @@
#pragma once
#ifdef NDEBUG
# define _SECURE_SCL 0
#endif
#define RL_MSVC_OUTPUT
#include "../../relacy/pch.hpp"
@@ -0,0 +1,20 @@
Microsoft Visual Studio Solution File, Format Version 9.00
# Visual Studio 2005
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "spsc_queue", "spsc_queue.vcproj", "{2F0B1A3B-27CA-47D4-A9D1-5EC66BB0A85B}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Win32 = Debug|Win32
Release|Win32 = Release|Win32
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{2F0B1A3B-27CA-47D4-A9D1-5EC66BB0A85B}.Debug|Win32.ActiveCfg = Debug|Win32
{2F0B1A3B-27CA-47D4-A9D1-5EC66BB0A85B}.Debug|Win32.Build.0 = Debug|Win32
{2F0B1A3B-27CA-47D4-A9D1-5EC66BB0A85B}.Release|Win32.ActiveCfg = Release|Win32
{2F0B1A3B-27CA-47D4-A9D1-5EC66BB0A85B}.Release|Win32.Build.0 = Release|Win32
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
EndGlobal
@@ -0,0 +1,207 @@
<?xml version="1.0" encoding="windows-1251"?>
<VisualStudioProject
ProjectType="Visual C++"
Version="8,00"
Name="spsc_queue"
ProjectGUID="{2F0B1A3B-27CA-47D4-A9D1-5EC66BB0A85B}"
RootNamespace="spsc_queue"
Keyword="Win32Proj"
>
<Platforms>
<Platform
Name="Win32"
/>
</Platforms>
<ToolFiles>
</ToolFiles>
<Configurations>
<Configuration
Name="Debug|Win32"
OutputDirectory="$(SolutionDir)$(ConfigurationName)"
IntermediateDirectory="$(ConfigurationName)"
ConfigurationType="1"
CharacterSet="1"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
/>
<Tool
Name="VCCLCompilerTool"
Optimization="0"
AdditionalIncludeDirectories="../.."
PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE"
MinimalRebuild="true"
BasicRuntimeChecks="3"
RuntimeLibrary="3"
UsePrecompiledHeader="2"
WarningLevel="4"
DebugInformationFormat="4"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
LinkIncremental="2"
GenerateDebugInformation="true"
SubSystem="1"
TargetMachine="1"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCWebDeploymentTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
<Configuration
Name="Release|Win32"
OutputDirectory="$(SolutionDir)$(ConfigurationName)"
IntermediateDirectory="$(ConfigurationName)"
ConfigurationType="1"
CharacterSet="1"
WholeProgramOptimization="1"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
/>
<Tool
Name="VCCLCompilerTool"
AdditionalIncludeDirectories="../../.."
PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE"
RuntimeLibrary="2"
UsePrecompiledHeader="2"
WarningLevel="4"
DebugInformationFormat="3"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
LinkIncremental="1"
GenerateDebugInformation="true"
SubSystem="1"
OptimizeReferences="2"
EnableCOMDATFolding="2"
TargetMachine="1"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCWebDeploymentTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
</Configurations>
<References>
</References>
<Files>
<File
RelativePath="..\spsc_queue.cpp"
>
</File>
<File
RelativePath="..\stdafx.cpp"
>
<FileConfiguration
Name="Debug|Win32"
>
<Tool
Name="VCCLCompilerTool"
UsePrecompiledHeader="1"
ObjectFile="$(IntDir)\$(InputName)1.obj"
XMLDocumentationFileName="$(IntDir)\$(InputName)1.xdc"
/>
</FileConfiguration>
<FileConfiguration
Name="Release|Win32"
>
<Tool
Name="VCCLCompilerTool"
UsePrecompiledHeader="1"
ObjectFile="$(IntDir)\$(InputName)1.obj"
XMLDocumentationFileName="$(IntDir)\$(InputName)1.xdc"
/>
</FileConfiguration>
</File>
<File
RelativePath="..\stdafx.h"
>
</File>
</Files>
<Globals>
</Globals>
</VisualStudioProject>
@@ -0,0 +1,20 @@
Microsoft Visual Studio Solution File, Format Version 10.00
# Visual Studio 2008
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "spsc_queue", "spsc_queue.vcproj", "{D4756EE9-3953-4E17-B1B5-E89F853303C1}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Win32 = Debug|Win32
Release|Win32 = Release|Win32
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{D4756EE9-3953-4E17-B1B5-E89F853303C1}.Debug|Win32.ActiveCfg = Debug|Win32
{D4756EE9-3953-4E17-B1B5-E89F853303C1}.Debug|Win32.Build.0 = Debug|Win32
{D4756EE9-3953-4E17-B1B5-E89F853303C1}.Release|Win32.ActiveCfg = Release|Win32
{D4756EE9-3953-4E17-B1B5-E89F853303C1}.Release|Win32.Build.0 = Release|Win32
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
EndGlobal
@@ -0,0 +1,200 @@
<?xml version="1.0" encoding="windows-1251"?>
<VisualStudioProject
ProjectType="Visual C++"
Version="9.00"
Name="spsc_queue"
ProjectGUID="{3F32C4FA-E451-42BC-9E65-74129120B6E4}"
RootNamespace="spsc_queue"
Keyword="Win32Proj"
TargetFrameworkVersion="131072"
>
<Platforms>
<Platform
Name="Win32"
/>
</Platforms>
<ToolFiles>
</ToolFiles>
<Configurations>
<Configuration
Name="Debug|Win32"
OutputDirectory="$(SolutionDir)$(ConfigurationName)"
IntermediateDirectory="$(ConfigurationName)"
ConfigurationType="1"
CharacterSet="1"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
/>
<Tool
Name="VCCLCompilerTool"
Optimization="0"
PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE"
MinimalRebuild="true"
BasicRuntimeChecks="3"
RuntimeLibrary="3"
UsePrecompiledHeader="2"
WarningLevel="4"
DebugInformationFormat="4"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
LinkIncremental="2"
GenerateDebugInformation="true"
SubSystem="1"
RandomizedBaseAddress="1"
DataExecutionPrevention="0"
TargetMachine="1"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
<Configuration
Name="Release|Win32"
OutputDirectory="$(SolutionDir)$(ConfigurationName)"
IntermediateDirectory="$(ConfigurationName)"
ConfigurationType="1"
CharacterSet="1"
WholeProgramOptimization="1"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
/>
<Tool
Name="VCCLCompilerTool"
PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE"
RuntimeLibrary="2"
UsePrecompiledHeader="2"
WarningLevel="4"
DebugInformationFormat="3"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
LinkIncremental="1"
GenerateDebugInformation="true"
SubSystem="1"
OptimizeReferences="2"
EnableCOMDATFolding="2"
RandomizedBaseAddress="1"
DataExecutionPrevention="0"
TargetMachine="1"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
</Configurations>
<References>
</References>
<Files>
<File
RelativePath="..\spsc_queue.cpp"
>
</File>
<File
RelativePath="..\stdafx.cpp"
>
<FileConfiguration
Name="Debug|Win32"
>
<Tool
Name="VCCLCompilerTool"
UsePrecompiledHeader="1"
/>
</FileConfiguration>
<FileConfiguration
Name="Release|Win32"
>
<Tool
Name="VCCLCompilerTool"
UsePrecompiledHeader="1"
/>
</FileConfiguration>
</File>
<File
RelativePath="..\stdafx.h"
>
</File>
</Files>
<Globals>
</Globals>
</VisualStudioProject>
@@ -0,0 +1,202 @@
#include "stdafx.h"
#include "../../relacy/relacy_std.hpp"
template<typename T>
class nonblocking_spsc_queue
{
public:
nonblocking_spsc_queue()
{
node* n = new node ();
VAR(head) = n;
VAR(tail) = n;
}
~nonblocking_spsc_queue()
{
RL_ASSERT(VAR(head) == VAR(tail));
delete (node*)VAR(head);
}
void enqueue(T data)
{
node* n = new node (data);
VAR(head)->next.store(n, std::memory_order_release);
VAR(head) = n;
}
bool dequeue(T& data)
{
node* t = VAR(tail);
node* n = t->next.load(std::memory_order_acquire);
if (0 == n)
return false;
data = n->VAR(data);
delete t;
VAR(tail) = n;
return true;
}
private:
struct node
{
std::atomic<node*> next;
VAR_T(T) data;
node(T data = T())
: next(0)
, data(data)
{}
};
VAR_T(node*) head;
VAR_T(node*) tail;
};
struct nonblocking_spsc_queue_test : rl::test_suite<nonblocking_spsc_queue_test, 2>
{
nonblocking_spsc_queue<int> q;
void thread(unsigned thread_index)
{
if (0 == thread_index)
{
q.enqueue(11);
}
else
{
int data = 0;
while (false == q.dequeue(data))
{}
RL_ASSERT(11 == data);
}
}
};
class eventcount
{
public:
eventcount()
: count(0)
, waiters(0)
{}
void signal_relaxed()
{
unsigned cmp = count.load(std::memory_order_relaxed);
signal_impl(cmp);
}
void signal()
{
unsigned cmp = count.fetch_add(0, std::memory_order_seq_cst);
signal_impl(cmp);
}
unsigned get()
{
unsigned cmp = count.fetch_or(0x80000000, std::memory_order_acquire);
return cmp & 0x7FFFFFFF;
}
void wait(unsigned cmp)
{
unsigned ec = count.load(std::memory_order_seq_cst);
if (cmp == (ec & 0x7FFFFFFF))
{
guard.lock($);
ec = count.load(std::memory_order_seq_cst);
if (cmp == (ec & 0x7FFFFFFF))
{
waiters($) += 1;
cv.wait(guard, $);
}
guard.unlock($);
}
}
private:
std::atomic<unsigned> count;
VAR_T(unsigned) waiters;
std::mutex guard;
std::condition_variable cv;
void signal_impl(unsigned cmp)
{
if (cmp & 0x80000000)
{
guard.lock($);
while (false == count.compare_exchange_weak(cmp,
(cmp + 1) & 0x7FFFFFFF, std::memory_order_relaxed));
unsigned w = VAR(waiters);
VAR(waiters) = 0;
guard.unlock($);
if (w)
cv.notify_all($);
}
}
};
template<typename T>
class spsc_queue : nonblocking_spsc_queue<T>
{
public:
typedef nonblocking_spsc_queue<T> base_t;
void enqueue(T data)
{
base_t::enqueue(data);
ec.signal/*_relaxed*/();
}
T dequeue()
{
T data;
bool res = base_t::dequeue(data);
while (false == res)
{
int cmp = ec.get();
res = base_t::dequeue(data);
if (res)
break;
ec.wait(cmp);
res = base_t::dequeue(data);
if (res)
break;
}
return data;
}
private:
eventcount ec;
};
struct spsc_queue_test : rl::test_suite<spsc_queue_test, 2>
{
spsc_queue<int> q;
void thread(unsigned thread_index)
{
if (0 == thread_index)
{
q.enqueue(11);
}
else
{
int d = q.dequeue();
RL_ASSERT(11 == d);
}
}
};
int main()
{
rl::simulate<nonblocking_spsc_queue_test>();
rl::simulate<spsc_queue_test>();
}
@@ -0,0 +1,2 @@
#include "stdafx.h"
@@ -0,0 +1,13 @@
#pragma once
#ifdef NDEBUG
# define _SECURE_SCL 0
#endif
//#define RL_MSVC_OUTPUT
#include "../../relacy/pch.hpp"
#include "../../relacy/relacy_std.hpp"
@@ -0,0 +1,2 @@
lock-free stack
code contains several bugs: access to freed memory and ABA problem
@@ -0,0 +1,20 @@
Microsoft Visual Studio Solution File, Format Version 9.00
# Visual Studio 2005
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "stack", "stack.vcproj", "{4D6D7FC3-66D1-4F80-B434-2FDCBBFBC9F5}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Win32 = Debug|Win32
Release|Win32 = Release|Win32
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{4D6D7FC3-66D1-4F80-B434-2FDCBBFBC9F5}.Debug|Win32.ActiveCfg = Debug|Win32
{4D6D7FC3-66D1-4F80-B434-2FDCBBFBC9F5}.Debug|Win32.Build.0 = Debug|Win32
{4D6D7FC3-66D1-4F80-B434-2FDCBBFBC9F5}.Release|Win32.ActiveCfg = Release|Win32
{4D6D7FC3-66D1-4F80-B434-2FDCBBFBC9F5}.Release|Win32.Build.0 = Release|Win32
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
EndGlobal
@@ -0,0 +1,201 @@
<?xml version="1.0" encoding="windows-1251"?>
<VisualStudioProject
ProjectType="Visual C++"
Version="8,00"
Name="stack"
ProjectGUID="{4D6D7FC3-66D1-4F80-B434-2FDCBBFBC9F5}"
RootNamespace="stack"
Keyword="Win32Proj"
>
<Platforms>
<Platform
Name="Win32"
/>
</Platforms>
<ToolFiles>
</ToolFiles>
<Configurations>
<Configuration
Name="Debug|Win32"
OutputDirectory="$(SolutionDir)$(ConfigurationName)"
IntermediateDirectory="$(ConfigurationName)"
ConfigurationType="1"
CharacterSet="1"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
/>
<Tool
Name="VCCLCompilerTool"
Optimization="0"
PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE"
MinimalRebuild="true"
BasicRuntimeChecks="3"
RuntimeLibrary="3"
UsePrecompiledHeader="2"
WarningLevel="4"
DebugInformationFormat="4"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
LinkIncremental="2"
GenerateDebugInformation="true"
SubSystem="1"
TargetMachine="1"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCWebDeploymentTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
<Configuration
Name="Release|Win32"
OutputDirectory="$(SolutionDir)$(ConfigurationName)"
IntermediateDirectory="$(ConfigurationName)"
ConfigurationType="1"
CharacterSet="1"
WholeProgramOptimization="1"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
/>
<Tool
Name="VCCLCompilerTool"
PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE"
RuntimeLibrary="2"
UsePrecompiledHeader="2"
WarningLevel="4"
DebugInformationFormat="3"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
LinkIncremental="1"
GenerateDebugInformation="true"
SubSystem="1"
OptimizeReferences="2"
EnableCOMDATFolding="2"
TargetMachine="1"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCWebDeploymentTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
</Configurations>
<References>
</References>
<Files>
<File
RelativePath="..\stack.cpp"
>
</File>
<File
RelativePath="..\stdafx.cpp"
>
<FileConfiguration
Name="Debug|Win32"
>
<Tool
Name="VCCLCompilerTool"
UsePrecompiledHeader="1"
/>
</FileConfiguration>
<FileConfiguration
Name="Release|Win32"
>
<Tool
Name="VCCLCompilerTool"
UsePrecompiledHeader="1"
/>
</FileConfiguration>
</File>
<File
RelativePath="..\stdafx.h"
>
</File>
</Files>
<Globals>
</Globals>
</VisualStudioProject>
@@ -0,0 +1,20 @@
Microsoft Visual Studio Solution File, Format Version 10.00
# Visual Studio 2008
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "stack", "stack.vcproj", "{4D6D7FC3-66D1-4F80-B434-2FDCBBFBC9F5}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Win32 = Debug|Win32
Release|Win32 = Release|Win32
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{4D6D7FC3-66D1-4F80-B434-2FDCBBFBC9F5}.Debug|Win32.ActiveCfg = Debug|Win32
{4D6D7FC3-66D1-4F80-B434-2FDCBBFBC9F5}.Debug|Win32.Build.0 = Debug|Win32
{4D6D7FC3-66D1-4F80-B434-2FDCBBFBC9F5}.Release|Win32.ActiveCfg = Release|Win32
{4D6D7FC3-66D1-4F80-B434-2FDCBBFBC9F5}.Release|Win32.Build.0 = Release|Win32
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
EndGlobal
@@ -0,0 +1,196 @@
<?xml version="1.0" encoding="windows-1251"?>
<VisualStudioProject
ProjectType="Visual C++"
Version="9.00"
Name="stack"
ProjectGUID="{4D6D7FC3-66D1-4F80-B434-2FDCBBFBC9F5}"
RootNamespace="stack"
Keyword="Win32Proj"
TargetFrameworkVersion="0"
>
<Platforms>
<Platform
Name="Win32"
/>
</Platforms>
<ToolFiles>
</ToolFiles>
<Configurations>
<Configuration
Name="Debug|Win32"
OutputDirectory="$(SolutionDir)$(ConfigurationName)"
IntermediateDirectory="$(ConfigurationName)"
ConfigurationType="1"
CharacterSet="1"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
/>
<Tool
Name="VCCLCompilerTool"
Optimization="0"
PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE"
MinimalRebuild="true"
BasicRuntimeChecks="3"
RuntimeLibrary="1"
UsePrecompiledHeader="2"
WarningLevel="4"
DebugInformationFormat="4"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
LinkIncremental="2"
GenerateDebugInformation="true"
SubSystem="1"
TargetMachine="1"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
<Configuration
Name="Release|Win32"
OutputDirectory="$(SolutionDir)$(ConfigurationName)"
IntermediateDirectory="$(ConfigurationName)"
ConfigurationType="1"
CharacterSet="1"
WholeProgramOptimization="1"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
/>
<Tool
Name="VCCLCompilerTool"
PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE"
RuntimeLibrary="0"
UsePrecompiledHeader="2"
WarningLevel="4"
DebugInformationFormat="3"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
LinkIncremental="1"
GenerateDebugInformation="true"
SubSystem="1"
OptimizeReferences="2"
EnableCOMDATFolding="2"
TargetMachine="1"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
</Configurations>
<References>
</References>
<Files>
<File
RelativePath="..\stack.cpp"
>
</File>
<File
RelativePath="..\stdafx.cpp"
>
<FileConfiguration
Name="Debug|Win32"
>
<Tool
Name="VCCLCompilerTool"
UsePrecompiledHeader="1"
/>
</FileConfiguration>
<FileConfiguration
Name="Release|Win32"
>
<Tool
Name="VCCLCompilerTool"
UsePrecompiledHeader="1"
/>
</FileConfiguration>
</File>
<File
RelativePath="..\stdafx.h"
>
</File>
</Files>
<Globals>
</Globals>
</VisualStudioProject>
@@ -0,0 +1,105 @@
#include "stdafx.h"
#include "../../relacy/relacy_std.hpp"
// TEST FAILS WITH "ACCESS TO FREED MEMORY"
class stack
{
public:
stack()
: head_(0)
{
}
void push(int data)
{
rl::var<node*> n = new node ();
n($)->data_($) = data;
node* next = head_.load(rl::memory_order_relaxed);
for (;;)
{
n($)->next_.store(next, rl::memory_order_relaxed);
if (head_.compare_exchange_weak(next, n($), rl::memory_order_release))
break;
}
}
int pop()
{
node* n = head_.load(rl::memory_order_relaxed);
for (;;)
{
if (0 == n)
break;
node* next = n->next_.load(rl::memory_order_relaxed);
if (head_.compare_exchange_weak(n, next, rl::memory_order_acquire))
break;
}
if (n)
{
int data = n->data_($);
delete n;
return data;
}
else
{
return 0;
}
}
private:
struct node
{
std::atomic<node*> next_;
rl::var<int> data_;
};
std::atomic<node*> head_;
stack(stack const&);
stack& operator = (stack const&);
};
struct stack_test : rl::test_suite<stack_test, 4>
{
stack s_;
int produced_count_;
int consumed_count_;
void before()
{
produced_count_ = 0;
consumed_count_ = 0;
}
void after()
{
typedef rl::test_suite<stack_test, 4> base_t;
RL_ASSERT(base_t::params::thread_count == produced_count_);
RL_ASSERT(base_t::params::thread_count == consumed_count_);
}
void thread(unsigned /*index*/)
{
s_.push(rand() + 1);
produced_count_ += 1;
int data = s_.pop();
RL_ASSERT(data);
consumed_count_ += 1;
}
};
int main()
{
rl::simulate<stack_test>();
}
@@ -0,0 +1,2 @@
#include "stdafx.h"
@@ -0,0 +1,8 @@
#pragma once
#ifdef NDEBUG
# define _SECURE_SCL 0
#endif
#include "../../relacy/pch.hpp"
@@ -0,0 +1,842 @@
#include "stdafx.h"
#include "../../relacy/windows.h"
/*
#define HANDLE rl::HANDLE
#define CreateSemaphoreA rl::RL_CreateSemaphore($)
#define CreateSemaphoreW rl::RL_CreateSemaphore($)
#ifndef CreateSemaphore
# define CreateSemaphore CreateSemaphoreW
#endif
//#define CRITICAL_SECTION rl::CRITICAL_SECTION
//#define InitializeCriticalSection rl::InitializeCriticalSection($)
#define CloseHandle rl::RL_CloseHandle($)
*/
#include <stddef.h>
#if defined(WIN32) && defined(_MSC_VER)
#include <windows.h>
#include <intrin.h>
class semaphore
{
public:
semaphore()
{
h_ = rl::CreateSemaphore(0, 0, LONG_MAX, 0, $);
}
~semaphore()
{
rl::CloseHandle(h_, $);
}
void wait()
{
rl::WaitForSingleObject(h_, rl::RL_INFINITE, $);
}
void post()
{
rl::ReleaseSemaphore(h_, 1, 0, $);
}
private:
rl::HANDLE h_;
semaphore(semaphore const&);
semaphore& operator = (semaphore const&);
};
class mutex
{
public:
mutex()
{
rl::InitializeCriticalSection(&cs_, $);
}
~mutex()
{
rl::DeleteCriticalSection(&cs_, $);
}
void lock()
{
rl::EnterCriticalSection(&cs_, $);
}
void unlock()
{
rl::LeaveCriticalSection(&cs_, $);
}
private:
rl::CRITICAL_SECTION cs_;
mutex(mutex const&);
mutex& operator = (mutex const&);
};
//void full_memory_fence()
//{
// _mm_mfence();
//}
//#define THREAD_LOCAL __declspec(thread)
#elif defined(POSIX) && defined(GCC)
#include <pthread.h>
#include <semaphore.h>
class semaphore
{
public:
semaphore()
{
sem_init(&sem_, 0, 0);
}
~semaphore()
{
sem_destroy(&sem_);
}
void wait()
{
sem_wait(&sem_);
}
void post()
{
sem_post(&sem_);
}
private:
sem_t sem_;
semaphore(semaphore const&);
semaphore& operator = (semaphore const&);
};
class mutex
{
public:
mutex()
{
pthread_mutex_init(&mutex_, 0);
}
~mutex()
{
pthread_mutex_destroy(&mutex_);
}
void lock()
{
pthread_mutex_lock(&mutex_);
}
void unlock()
{
pthread_mutex_unlock(&mutex_);
}
private:
pthread_mutex_t mutex_;
mutex(mutex const&);
mutex& operator = (mutex const&);
};
void full_memory_fence()
{
__sync_synchronize();
}
//#define THREAD_LOCAL __thread
#endif
class lock
{
public:
lock(mutex& m)
: m_(m)
{
m.lock();
}
~lock()
{
m_.unlock();
}
private:
mutex& m_;
lock(lock const&);
lock& operator = (lock const&);
};
/** simple single-threaded double-linked list
* nothing interesting
*/
class dlist
{
public:
struct node
{
rl::var<node*> prev_;
rl::var<node*> next_;
node()
{
prev_($) = 0;
next_($) = 0;
}
};
dlist()
{
reset();
}
void push(node* n)
{
size_t s = size_($).load(rl::memory_order_relaxed);
size_($).store(s + 1, rl::memory_order_relaxed);
n->next_($) = head_.next_($);
n->prev_($) = &head_;
head_.next_($)->prev_($) = n;
head_.next_($) = n;
}
node* pop()
{
if (size_($).load(rl::memory_order_relaxed) == 0)
return 0;
node* n = head_.next_($);
remove(n);
return n;
}
void remove(node* n)
{
size_t s = size_($).load(rl::memory_order_relaxed);
size_($).store(s - 1, rl::memory_order_relaxed);
n->prev_($)->next_($) = n->next_($);
n->next_($)->prev_($) = n->prev_($);
}
size_t size() const
{
return size_($).load(rl::memory_order_relaxed);
}
node* begin()
{
return head_.next_($);
}
void flush_to(dlist& target)
{
if (size_($).load(rl::memory_order_relaxed))
{
target.size_($).store(size_($).load(rl::memory_order_relaxed));
target.head_.next_($) = head_.next_($);
target.head_.next_($)->prev_($) = &target.head_;
target.tail_.prev_($) = tail_.prev_($);
target.tail_.prev_($)->next_($) = &target.tail_;
}
else
{
target.reset();
}
reset();
}
static bool not_last(node* n)
{
return n->next_($) != 0;
}
static node* get_next(node* n)
{
return n->next_($);
}
private:
rl::atomic<size_t> size_;
node head_;
node tail_;
void reset()
{
size_($) = 0;
head_.next_($) = &tail_;
head_.prev_($) = 0;
tail_.next_($) = 0;
tail_.prev_($) = &head_;
}
dlist(dlist const&);
dlist& operator = (dlist const&);
};
/** pre-thread descriptor for eventcount
*/
struct ec_thread
{
dlist::node node_;
semaphore sema_;
rl::var<unsigned> epoch_;
rl::atomic<bool> in_waitset_;
rl::var<bool> spurious_;
rl::var<void*> ctx_;
ec_thread()
{
epoch_($) = 0;
in_waitset_($) = false;
spurious_($) = false;
ctx_($) = 0;
}
~ec_thread()
{
if (spurious_($))
sema_.wait();
}
/*
static ec_thread* current()
{
static THREAD_LOCAL ec_thread* ec_thread_instance = 0;
ec_thread* instance = ec_thread_instance;
if (instance == 0)
{
instance = new ec_thread;
ec_thread_instance = instance;
}
return instance;
// instance must be destroyed in DllMain() callback
// or in pthread_key_create() callback
}
*/
private:
ec_thread(ec_thread const&);
ec_thread& operator = (ec_thread const&);
};
/** fine-grained eventcount implementation
*/
class eventcount
{
public:
eventcount()
{
epoch_($) = 0;
}
void prepare_wait(ec_thread* th = 0, void* ctx = 0)
{
RL_ASSERT(th);
// this is good place to pump previous spurious wakeup
if (th->spurious_($))
{
th->spurious_($) = false;
th->sema_.wait();
}
th->in_waitset_($).store(true, rl::memory_order_relaxed);
th->ctx_($) = ctx;
{
lock l (mtx_);
th->epoch_($) = epoch_($).load(rl::memory_order_relaxed);
waitset_.push(&th->node_);
}
rl::atomic_thread_fence($)(rl::memory_order_seq_cst);
}
void commit_wait(ec_thread* th = 0)
{
RL_ASSERT(th);
// this check is just an optimization
//if (th->epoch_($) == epoch_($).load(rl::memory_order_relaxed))
if (th->in_waitset_($).load(rl::memory_order_acquire))
th->sema_.wait();
else
cancel_wait(true, th); //!!! add 'th'
}
void cancel_wait(bool /*from_commit*/, ec_thread* th = 0)
{
RL_ASSERT(th);
// spurious wakeup will be pumped in the following prepare_wait()
th->spurious_($) = true;
// try to remove node from waitset
if (th->in_waitset_($).load(rl::memory_order_acquire))
{
lock l (mtx_);
if (th->in_waitset_($).load(rl::memory_order_relaxed))
{
// successfully removed from waitset,
// so there will be no spurious wakeup
th->in_waitset_($).store(false, rl::memory_order_relaxed);
th->spurious_($) = false;
waitset_.remove(&th->node_);
}
else
{
//if (from_commit)
//int volatile x = 0;
}
}
else
{
//RL_ASSERT(from_commit == false);
//if (from_commit)
// int volatile x = 0;
}
}
void notify_one()
{
rl::atomic_thread_fence($)(rl::memory_order_seq_cst);
notify_one_relaxed();
}
template<typename predicate_t>
void notify(predicate_t pred)
{
rl::atomic_thread_fence($)(rl::memory_order_seq_cst);
notify_relaxed(pred);
}
void notify_all()
{
rl::atomic_thread_fence($)(rl::memory_order_seq_cst);
notify_all_relaxed();
}
void notify_one_relaxed()
{
if (waitset_.size() == 0)
return;
dlist::node* n;
{
lock l (mtx_);
unsigned ep = epoch_($).load(rl::memory_order_relaxed);
epoch_($).store(ep + 1, rl::memory_order_relaxed);
n = waitset_.pop();
if (n)
to_ec_thread(n)->in_waitset_($).store(false, rl::memory_order_release);
}
if (n)
{
to_ec_thread(n)->sema_.post();
}
}
template<typename predicate_t>
void notify_relaxed(predicate_t pred)
{
if (waitset_.size() == 0)
return;
dlist temp;
{
lock l (mtx_);
unsigned ep = epoch_($).load(rl::memory_order_relaxed);
epoch_($).store(ep + 1, rl::memory_order_relaxed);
size_t size = waitset_.size();
size_t idx = 0;
dlist::node* n = waitset_.begin();
while (dlist::not_last(n))
{
dlist::node* next = dlist::get_next(n);
ec_thread* th = to_ec_thread(n);
if (pred(th->ctx_($), size, idx))
{
waitset_.remove(n);
temp.push(n);
th->in_waitset_($).store(false, rl::memory_order_release);
}
n = next;
idx += 1;
}
}
dlist::node* n = temp.begin();
while (dlist::not_last(n))
{
dlist::node* next = dlist::get_next(n);
to_ec_thread(n)->sema_.post();
n = next;
}
}
void notify_all_relaxed()
{
if (waitset_.size() == 0)
return;
dlist temp;
{
lock l (mtx_);
waitset_.flush_to(temp);
dlist::node* n = temp.begin();
while (dlist::not_last(n))
{
to_ec_thread(n)->in_waitset_($).store(false, rl::memory_order_release);
n = dlist::get_next(n);
}
unsigned ep = epoch_($).load(rl::memory_order_relaxed);
epoch_($).store(ep + 1, rl::memory_order_relaxed);
}
dlist::node* n = temp.begin();
while (dlist::not_last(n))
{
dlist::node* next = dlist::get_next(n);
to_ec_thread(n)->sema_.post();
n = next;
}
}
class wait_guard;
private:
mutex mtx_;
dlist waitset_;
rl::atomic<unsigned>epoch_;
ec_thread* to_ec_thread(dlist::node* n)
{
return (ec_thread*)((char*)n - offsetof(ec_thread, node_));
}
eventcount(eventcount const&);
eventcount& operator = (eventcount const&);
};
class eventcount::wait_guard
{
public:
wait_guard(eventcount& ec, ec_thread* th = 0, void* ctx = 0)
: ec_(ec)
, th_(th)
, wait_(false)
{
ec_.prepare_wait(th_, ctx);
}
void commit_wait()
{
assert(false == wait_);
wait_ = true;
ec_.commit_wait(th_);
}
~wait_guard()
{
if (false == wait_)
ec_.cancel_wait(false, th_);
}
private:
eventcount& ec_;
ec_thread* th_;
bool wait_;
wait_guard(wait_guard const&);
wait_guard& operator = (wait_guard const&);
};
struct scheduler
{
struct tbb_thread
{
ec_thread th;
};
eventcount ec_;
tbb_thread* threads_;
bool volatile is_permanently_open_;
void wait_while_pool_is_empty(tbb_thread* th)
{
if (is_permanently_open_)
return;
eventcount::wait_guard wait (ec_, &th->th);
if (pool_is_empty())
wait.commit_wait();
}
void notify_about_new_task_available()
{
ec_.notify_one_relaxed();
}
void notify_about_new_task_available_with_preference(tbb_thread* preference)
{
struct local
{
tbb_thread* preference_;
bool fired_;
bool operator () (void* ctx, size_t count, size_t idx)
{
tbb_thread* th = (tbb_thread*)ctx;
if (th == preference_)
{
fired_ = true;
return true;
}
else if (idx == count - 1 && fired_ == false)
{
return true;
}
else
{
return false;
}
}
}
pred = {preference};
ec_.notify_relaxed(pred);
}
void notify_about_list_of_tasks_available(size_t total_count, size_t preference_count, tbb_thread** preferences)
{
struct local
{
size_t remain_to_signal_;
size_t preference_count_;
tbb_thread** preferences_;
bool operator () (void* ctx, size_t count, size_t idx)
{
tbb_thread* th = (tbb_thread*)ctx;
size_t remain_in_waitset = count - idx;
if (remain_in_waitset <= remain_to_signal_)
{
return true;
}
else
{
for (size_t i = 0; i != preference_count_; ++i)
{
if (preferences_[i] == th)
{
remain_to_signal_ -= 1;
return true;
}
}
}
return false;
}
}
pred = {total_count, preference_count, preferences};
ec_.notify_relaxed(pred);
}
bool pool_is_empty()
{
return true;
}
};
struct queue
{
rl::atomic<int> producer_idx_;
rl::atomic<int> consumer_idx_;
rl::atomic<void*>* buffer_;
eventcount ec_;
queue()
{
producer_idx_($) = 0;
consumer_idx_($) = 0;
buffer_ = RL_NEW_ARR(rl::atomic<void*>, 10);
for (size_t i = 0; i != 10; ++i)
buffer_[i]($) = 0;
}
~queue()
{
RL_DELETE_ARR(buffer_);
}
void enqueue(void* data)
{
int idx = producer_idx_($).fetch_add(1) + 1; // atomic
buffer_[idx]($).store(data, rl::memory_order_relaxed);
struct local
{
int idx_;
bool operator () (void* ctx, size_t /*count*/, size_t /*idx*/)
{
return idx_ == (*(rl::var<int>*)ctx)($);
}
}
pred = {idx};
ec_.notify(pred); // not relaxed!!!
}
void* dequeue(ec_thread* th)
{
int idx = consumer_idx_($).fetch_add(1) + 1; // atomic
void* data = buffer_[idx]($).load(rl::memory_order_relaxed);
if (data)
return data;
for (;;)
{
rl::var<int> idxv (idx);
eventcount::wait_guard wait (ec_, th, &idxv);
data = buffer_[idx]($).load(rl::memory_order_relaxed);
if (data)
{
return data;
}
wait.commit_wait();
idxv($) = 0;
data = buffer_[idx]($).load(rl::memory_order_relaxed);
if (data)
{
return data;
}
rl::yield($, 1);
//RL_ASSERT(false);
}
}
};
class condition_variable
{
eventcount ec_;
public:
void wait(mutex& mtx, ec_thread* th)
{
eventcount::wait_guard wait (ec_, th);
mtx.unlock();
wait.commit_wait();
mtx.lock();
}
void signal()
{
ec_.notify_one();
}
void broadcast()
{
ec_.notify_all();
}
};
struct queue_test : rl::test_suite<queue_test, 4>
{
ec_thread threads_ [6];
queue q_;
void thread(unsigned index)
{
if (index < 2)
{
q_.enqueue((void*)(index*2+1));
q_.enqueue((void*)(index*2+2));
}
else
{
int data1 = (int)q_.dequeue(&threads_[index]);
RL_ASSERT(data1 >= 1 && data1 <= 6);
int data2 = (int)q_.dequeue(&threads_[index]);
RL_ASSERT(data2 >= 1 && data2 <= 6);
}
}
};
struct condvar_test : rl::test_suite<condvar_test, 3>
{
rl::var<int> stage;
condition_variable cv;
mutex mtx;
ec_thread th [3];
void before()
{
stage($) = 0;
}
void thread(unsigned index)
{
if (0 == index)
{
mtx.lock();
stage($) += 1;
cv.broadcast();
while (stage($) != 2)
cv.wait(mtx, &th[index]);
mtx.unlock();
}
else if (1 == index)
{
mtx.lock();
while (stage($) != 1)
cv.wait(mtx, &th[index]);
stage($) += 1;
cv.broadcast();
mtx.unlock();
}
else if (2 == index)
{
mtx.lock();
while (stage($) != 2)
cv.wait(mtx, &th[index]);
mtx.unlock();
}
}
};
int main()
{
rl::test_params p;
p.iteration_count = 100000000;
//p.initial_state = "30000000";
//p.search_type = rl::fair_context_bound_scheduler_type;
rl::simulate<queue_test>(p);
//rl::simulate<condvar_test>(p);
}
@@ -0,0 +1,20 @@
Microsoft Visual Studio Solution File, Format Version 9.00
# Visual Studio 2005
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "eventcount", "eventcount.vcproj", "{ECB64178-A35E-4EB2-9EB0-BD72D6F7B6E5}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Win32 = Debug|Win32
Release|Win32 = Release|Win32
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{ECB64178-A35E-4EB2-9EB0-BD72D6F7B6E5}.Debug|Win32.ActiveCfg = Debug|Win32
{ECB64178-A35E-4EB2-9EB0-BD72D6F7B6E5}.Debug|Win32.Build.0 = Debug|Win32
{ECB64178-A35E-4EB2-9EB0-BD72D6F7B6E5}.Release|Win32.ActiveCfg = Release|Win32
{ECB64178-A35E-4EB2-9EB0-BD72D6F7B6E5}.Release|Win32.Build.0 = Release|Win32
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
EndGlobal
@@ -0,0 +1,203 @@
<?xml version="1.0" encoding="windows-1251"?>
<VisualStudioProject
ProjectType="Visual C++"
Version="8,00"
Name="eventcount"
ProjectGUID="{ECB64178-A35E-4EB2-9EB0-BD72D6F7B6E5}"
RootNamespace="eventcount"
Keyword="Win32Proj"
>
<Platforms>
<Platform
Name="Win32"
/>
</Platforms>
<ToolFiles>
</ToolFiles>
<Configurations>
<Configuration
Name="Debug|Win32"
OutputDirectory="$(SolutionDir)$(ConfigurationName)"
IntermediateDirectory="$(ConfigurationName)"
ConfigurationType="1"
CharacterSet="1"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
/>
<Tool
Name="VCCLCompilerTool"
Optimization="0"
PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE"
MinimalRebuild="true"
BasicRuntimeChecks="3"
RuntimeLibrary="3"
UsePrecompiledHeader="2"
WarningLevel="4"
Detect64BitPortabilityProblems="false"
DebugInformationFormat="4"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
LinkIncremental="2"
GenerateDebugInformation="true"
SubSystem="1"
TargetMachine="1"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCWebDeploymentTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
<Configuration
Name="Release|Win32"
OutputDirectory="$(SolutionDir)$(ConfigurationName)"
IntermediateDirectory="$(ConfigurationName)"
ConfigurationType="1"
CharacterSet="1"
WholeProgramOptimization="1"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
/>
<Tool
Name="VCCLCompilerTool"
PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE"
RuntimeLibrary="2"
UsePrecompiledHeader="2"
WarningLevel="4"
Detect64BitPortabilityProblems="false"
DebugInformationFormat="3"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
LinkIncremental="1"
GenerateDebugInformation="true"
SubSystem="1"
OptimizeReferences="2"
EnableCOMDATFolding="2"
TargetMachine="1"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCWebDeploymentTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
</Configurations>
<References>
</References>
<Files>
<File
RelativePath="..\stdafx.cpp"
>
<FileConfiguration
Name="Debug|Win32"
>
<Tool
Name="VCCLCompilerTool"
UsePrecompiledHeader="1"
/>
</FileConfiguration>
<FileConfiguration
Name="Release|Win32"
>
<Tool
Name="VCCLCompilerTool"
UsePrecompiledHeader="1"
/>
</FileConfiguration>
</File>
<File
RelativePath="..\stdafx.h"
>
</File>
<File
RelativePath="..\eventcount.cpp"
>
</File>
</Files>
<Globals>
</Globals>
</VisualStudioProject>
@@ -0,0 +1,20 @@
Microsoft Visual Studio Solution File, Format Version 10.00
# Visual Studio 2005
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "eventcount", "eventcount.vcproj", "{ECB64178-A35E-4EB2-9EB0-BD72D6F7B6E5}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Win32 = Debug|Win32
Release|Win32 = Release|Win32
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{ECB64178-A35E-4EB2-9EB0-BD72D6F7B6E5}.Debug|Win32.ActiveCfg = Debug|Win32
{ECB64178-A35E-4EB2-9EB0-BD72D6F7B6E5}.Debug|Win32.Build.0 = Debug|Win32
{ECB64178-A35E-4EB2-9EB0-BD72D6F7B6E5}.Release|Win32.ActiveCfg = Release|Win32
{ECB64178-A35E-4EB2-9EB0-BD72D6F7B6E5}.Release|Win32.Build.0 = Release|Win32
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
EndGlobal
@@ -0,0 +1,203 @@
<?xml version="1.0" encoding="windows-1251"?>
<VisualStudioProject
ProjectType="Visual C++"
Version="9,00"
Name="eventcount"
ProjectGUID="{ECB64178-A35E-4EB2-9EB0-BD72D6F7B6E5}"
RootNamespace="eventcount"
Keyword="Win32Proj"
>
<Platforms>
<Platform
Name="Win32"
/>
</Platforms>
<ToolFiles>
</ToolFiles>
<Configurations>
<Configuration
Name="Debug|Win32"
OutputDirectory="$(SolutionDir)$(ConfigurationName)"
IntermediateDirectory="$(ConfigurationName)"
ConfigurationType="1"
CharacterSet="1"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
/>
<Tool
Name="VCCLCompilerTool"
Optimization="0"
PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE"
MinimalRebuild="true"
BasicRuntimeChecks="3"
RuntimeLibrary="3"
UsePrecompiledHeader="2"
WarningLevel="4"
Detect64BitPortabilityProblems="false"
DebugInformationFormat="4"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
LinkIncremental="2"
GenerateDebugInformation="true"
SubSystem="1"
TargetMachine="1"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCWebDeploymentTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
<Configuration
Name="Release|Win32"
OutputDirectory="$(SolutionDir)$(ConfigurationName)"
IntermediateDirectory="$(ConfigurationName)"
ConfigurationType="1"
CharacterSet="1"
WholeProgramOptimization="1"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
/>
<Tool
Name="VCCLCompilerTool"
PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE"
RuntimeLibrary="2"
UsePrecompiledHeader="2"
WarningLevel="4"
Detect64BitPortabilityProblems="false"
DebugInformationFormat="3"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
LinkIncremental="1"
GenerateDebugInformation="true"
SubSystem="1"
OptimizeReferences="2"
EnableCOMDATFolding="2"
TargetMachine="1"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCWebDeploymentTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
</Configurations>
<References>
</References>
<Files>
<File
RelativePath="..\stdafx.cpp"
>
<FileConfiguration
Name="Debug|Win32"
>
<Tool
Name="VCCLCompilerTool"
UsePrecompiledHeader="1"
/>
</FileConfiguration>
<FileConfiguration
Name="Release|Win32"
>
<Tool
Name="VCCLCompilerTool"
UsePrecompiledHeader="1"
/>
</FileConfiguration>
</File>
<File
RelativePath="..\stdafx.h"
>
</File>
<File
RelativePath="..\eventcount.cpp"
>
</File>
</Files>
<Globals>
</Globals>
</VisualStudioProject>
@@ -0,0 +1,8 @@
// stdafx.cpp : source file that includes just the standard includes
// ws_deque.pch will be the pre-compiled header
// stdafx.obj will contain the pre-compiled type information
#include "stdafx.h"
// TODO: reference any additional headers you need in STDAFX.H
// and not in this file
@@ -0,0 +1,6 @@
#pragma once
#include "../../relacy/pch.hpp"
#include "../../relacy/relacy_std.hpp"
@@ -0,0 +1,20 @@
Microsoft Visual Studio Solution File, Format Version 9.00
# Visual Studio 2005
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ws_deque", "ws_deque.vcproj", "{0B597F19-DEBB-4832-B520-9A93A286D595}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Win32 = Debug|Win32
Release|Win32 = Release|Win32
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{0B597F19-DEBB-4832-B520-9A93A286D595}.Debug|Win32.ActiveCfg = Debug|Win32
{0B597F19-DEBB-4832-B520-9A93A286D595}.Debug|Win32.Build.0 = Debug|Win32
{0B597F19-DEBB-4832-B520-9A93A286D595}.Release|Win32.ActiveCfg = Release|Win32
{0B597F19-DEBB-4832-B520-9A93A286D595}.Release|Win32.Build.0 = Release|Win32
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
EndGlobal
@@ -0,0 +1,205 @@
<?xml version="1.0" encoding="windows-1251"?>
<VisualStudioProject
ProjectType="Visual C++"
Version="8,00"
Name="ws_deque"
ProjectGUID="{0B597F19-DEBB-4832-B520-9A93A286D595}"
RootNamespace="ws_deque"
Keyword="Win32Proj"
>
<Platforms>
<Platform
Name="Win32"
/>
</Platforms>
<ToolFiles>
</ToolFiles>
<Configurations>
<Configuration
Name="Debug|Win32"
OutputDirectory="$(SolutionDir)$(ConfigurationName)"
IntermediateDirectory="$(ConfigurationName)"
ConfigurationType="1"
CharacterSet="1"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
/>
<Tool
Name="VCCLCompilerTool"
Optimization="0"
PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE"
MinimalRebuild="true"
BasicRuntimeChecks="3"
RuntimeLibrary="3"
UsePrecompiledHeader="2"
WarningLevel="4"
DebugInformationFormat="4"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
LinkIncremental="2"
GenerateDebugInformation="true"
SubSystem="1"
TargetMachine="1"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCWebDeploymentTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
<Configuration
Name="Release|Win32"
OutputDirectory="$(SolutionDir)$(ConfigurationName)"
IntermediateDirectory="$(ConfigurationName)"
ConfigurationType="1"
CharacterSet="1"
WholeProgramOptimization="1"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
/>
<Tool
Name="VCCLCompilerTool"
PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE"
RuntimeLibrary="2"
UsePrecompiledHeader="2"
WarningLevel="4"
DebugInformationFormat="3"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
LinkIncremental="1"
GenerateDebugInformation="true"
SubSystem="1"
OptimizeReferences="2"
EnableCOMDATFolding="2"
TargetMachine="1"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCWebDeploymentTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
</Configurations>
<References>
</References>
<Files>
<File
RelativePath="..\stdafx.cpp"
>
<FileConfiguration
Name="Debug|Win32"
>
<Tool
Name="VCCLCompilerTool"
UsePrecompiledHeader="1"
ObjectFile="$(IntDir)\$(InputName)1.obj"
XMLDocumentationFileName="$(IntDir)\$(InputName)1.xdc"
/>
</FileConfiguration>
<FileConfiguration
Name="Release|Win32"
>
<Tool
Name="VCCLCompilerTool"
UsePrecompiledHeader="1"
ObjectFile="$(IntDir)\$(InputName)1.obj"
XMLDocumentationFileName="$(IntDir)\$(InputName)1.xdc"
/>
</FileConfiguration>
</File>
<File
RelativePath="..\stdafx.h"
>
</File>
<File
RelativePath="..\ws_deque.cpp"
>
</File>
</Files>
<Globals>
</Globals>
</VisualStudioProject>
@@ -0,0 +1,20 @@
Microsoft Visual Studio Solution File, Format Version 10.00
# Visual Studio 2008
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ws_deque", "ws_deque.vcproj", "{0B597F19-DEBB-4832-B520-9A93A286D595}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Win32 = Debug|Win32
Release|Win32 = Release|Win32
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{0B597F19-DEBB-4832-B520-9A93A286D595}.Debug|Win32.ActiveCfg = Debug|Win32
{0B597F19-DEBB-4832-B520-9A93A286D595}.Debug|Win32.Build.0 = Debug|Win32
{0B597F19-DEBB-4832-B520-9A93A286D595}.Release|Win32.ActiveCfg = Release|Win32
{0B597F19-DEBB-4832-B520-9A93A286D595}.Release|Win32.Build.0 = Release|Win32
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
EndGlobal
@@ -0,0 +1,205 @@
<?xml version="1.0" encoding="windows-1251"?>
<VisualStudioProject
ProjectType="Visual C++"
Version="9,00"
Name="ws_deque"
ProjectGUID="{0B597F19-DEBB-4832-B520-9A93A286D595}"
RootNamespace="ws_deque"
Keyword="Win32Proj"
>
<Platforms>
<Platform
Name="Win32"
/>
</Platforms>
<ToolFiles>
</ToolFiles>
<Configurations>
<Configuration
Name="Debug|Win32"
OutputDirectory="$(SolutionDir)$(ConfigurationName)"
IntermediateDirectory="$(ConfigurationName)"
ConfigurationType="1"
CharacterSet="1"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
/>
<Tool
Name="VCCLCompilerTool"
Optimization="0"
PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE"
MinimalRebuild="true"
BasicRuntimeChecks="3"
RuntimeLibrary="3"
UsePrecompiledHeader="2"
WarningLevel="4"
DebugInformationFormat="4"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
LinkIncremental="2"
GenerateDebugInformation="true"
SubSystem="1"
TargetMachine="1"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCWebDeploymentTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
<Configuration
Name="Release|Win32"
OutputDirectory="$(SolutionDir)$(ConfigurationName)"
IntermediateDirectory="$(ConfigurationName)"
ConfigurationType="1"
CharacterSet="1"
WholeProgramOptimization="1"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
/>
<Tool
Name="VCCLCompilerTool"
PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE"
RuntimeLibrary="2"
UsePrecompiledHeader="2"
WarningLevel="4"
DebugInformationFormat="3"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
LinkIncremental="1"
GenerateDebugInformation="true"
SubSystem="1"
OptimizeReferences="2"
EnableCOMDATFolding="2"
TargetMachine="1"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCWebDeploymentTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
</Configurations>
<References>
</References>
<Files>
<File
RelativePath="..\stdafx.cpp"
>
<FileConfiguration
Name="Debug|Win32"
>
<Tool
Name="VCCLCompilerTool"
UsePrecompiledHeader="1"
ObjectFile="$(IntDir)\$(InputName)1.obj"
XMLDocumentationFileName="$(IntDir)\$(InputName)1.xdc"
/>
</FileConfiguration>
<FileConfiguration
Name="Release|Win32"
>
<Tool
Name="VCCLCompilerTool"
UsePrecompiledHeader="1"
ObjectFile="$(IntDir)\$(InputName)1.obj"
XMLDocumentationFileName="$(IntDir)\$(InputName)1.xdc"
/>
</FileConfiguration>
</File>
<File
RelativePath="..\stdafx.h"
>
</File>
<File
RelativePath="..\ws_deque.cpp"
>
</File>
</Files>
<Globals>
</Globals>
</VisualStudioProject>
@@ -0,0 +1,2 @@
#include "stdafx.h"
@@ -0,0 +1,14 @@
#pragma once
#ifdef NDEBUG
# define _SECURE_SCL 0
#endif
#define RL_MSVC_OUTPUT
//#define RL_DEBUGBREAK_ON_FAILURE
#include "../../relacy/pch.hpp"
#include "../../relacy/relacy_std.hpp"

Some files were not shown because too many files have changed in this diff Show More