mirror of
https://github.com/intrepidcs/libicsneo.git
synced 2026-08-05 17:38:35 +02:00
Add ReaderWriterQueue and update ConcurrentQueue
This commit is contained in:
@@ -0,0 +1,25 @@
|
||||
Version 2.4
|
||||
Features:
|
||||
+ Support for futex(FUTEX_WAIT/FUTEX_WAKE)
|
||||
+ Linux/Darwin performance improved (2.5x for Linux, 7x for Darwin)
|
||||
Fixes:
|
||||
+ Fixed a bunch of issues with WaitForMultipleObjects()/SignalObjectAndWait()
|
||||
+ Fixed rare spurious memory leak reports related to test progress reporting
|
||||
|
||||
Version 2.3
|
||||
Features:
|
||||
+ Support for FlushProcessWriteBuffers()
|
||||
|
||||
Version 2.2
|
||||
Features:
|
||||
+ Support for pthread_mutex_timedlock()
|
||||
+ Support for ETIMEDOUT, EINTR in pthread_cond_timedwait()/pthread_cond_wait()
|
||||
+ rl::hash_ptr(p, sz) function which provides deterministic hashing of pointers
|
||||
Fixes:
|
||||
+ Win32 mutex is now recursive
|
||||
+ Compilation issue on MSVC x64 when RL_DEBUGBREAK_ON_ASSERT/RL_DEBUGBREAK_ON_FAILURE defined
|
||||
+ Fixed OOM crash when execution history is very large
|
||||
+ Fixed rare crash during iteration count estimation in context bound scheduler
|
||||
+ Fixed bug in pthread_rwlock/SRWLOCK that at most 2 readers may acquire it simultaneously
|
||||
+ Fixed bug regarding false race detection when simulation runs for very long time (int overflow)
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
Relacy Race Detector
|
||||
Copyright (c) 2008-2013, Dmitry S. Vyukov
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
- Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
- Redistributions in binary form must reproduce the above copyright notice, this list of conditions
|
||||
and the following disclaimer in the documentation and/or other materials provided with the distribution.
|
||||
- The name of the owner may not be used to endorse or promote products derived from this software
|
||||
without specific prior written permission.
|
||||
THIS SOFTWARE IS PROVIDED BY THE OWNER "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
||||
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
IN NO EVENT SHALL THE OWNER BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
|
||||
OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
|
||||
EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
@@ -0,0 +1 @@
|
||||
acc09bbe65a1837a08912774c7fed178547514e6
|
||||
include/icsneo/third-party/concurrentqueue/tests/relacy/relacy/example/cli_ws_deque/cli_ws_deque.cpp
Vendored
+195
@@ -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>();
|
||||
}
|
||||
|
||||
+20
@@ -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
|
||||
+205
@@ -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>
|
||||
Vendored
+2
@@ -0,0 +1,2 @@
|
||||
#include "stdafx.h"
|
||||
|
||||
Vendored
+7
@@ -0,0 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
|
||||
#include "../../relacy/pch.hpp"
|
||||
|
||||
|
||||
|
||||
+181
@@ -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>();
|
||||
}
|
||||
|
||||
Vendored
+20
@@ -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
|
||||
Vendored
+205
@@ -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>
|
||||
Vendored
+20
@@ -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
|
||||
Vendored
+205
@@ -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>
|
||||
+2
@@ -0,0 +1,2 @@
|
||||
#include "stdafx.h"
|
||||
|
||||
+14
@@ -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"
|
||||
|
||||
|
||||
|
||||
include/icsneo/third-party/concurrentqueue/tests/relacy/relacy/example/eao_blocking/eao_blocking.cpp
Vendored
+178
@@ -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);
|
||||
}
|
||||
};
|
||||
*/
|
||||
Vendored
+707
@@ -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);
|
||||
}
|
||||
|
||||
+20
@@ -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
|
||||
+203
@@ -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>
|
||||
+20
@@ -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
|
||||
+203
@@ -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>
|
||||
Vendored
+8
@@ -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
|
||||
+10
@@ -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"
|
||||
|
||||
Vendored
+316
@@ -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);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
Vendored
+17
@@ -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);
|
||||
}
|
||||
|
||||
Vendored
+20
@@ -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
|
||||
+208
@@ -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>
|
||||
+202
@@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
+2
@@ -0,0 +1,2 @@
|
||||
#include "stdafx.h"
|
||||
|
||||
+16
@@ -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"
|
||||
|
||||
|
||||
|
||||
+195
@@ -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>();
|
||||
}
|
||||
|
||||
+20
@@ -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
|
||||
+205
@@ -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>
|
||||
Vendored
+2
@@ -0,0 +1,2 @@
|
||||
#include "stdafx.h"
|
||||
|
||||
Vendored
+7
@@ -0,0 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
|
||||
#include "../../relacy/pch.hpp"
|
||||
|
||||
|
||||
|
||||
+511
@@ -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);
|
||||
}
|
||||
|
||||
+20
@@ -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
|
||||
Vendored
+207
@@ -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>
|
||||
+481
@@ -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();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
+8
@@ -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
|
||||
+10
@@ -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"
|
||||
|
||||
+20
@@ -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
|
||||
+205
@@ -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>
|
||||
+131
@@ -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>();
|
||||
}
|
||||
|
||||
+2
@@ -0,0 +1,2 @@
|
||||
#include "stdafx.h"
|
||||
|
||||
include/icsneo/third-party/concurrentqueue/tests/relacy/relacy/example/mutex_business_logic/stdafx.h
Vendored
+14
@@ -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"
|
||||
|
||||
|
||||
|
||||
Vendored
+20
@@ -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
|
||||
+205
@@ -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>
|
||||
Vendored
+20
@@ -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
|
||||
+200
@@ -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>
|
||||
Vendored
+469
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
+2
@@ -0,0 +1,2 @@
|
||||
#include "stdafx.h"
|
||||
|
||||
+14
@@ -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"
|
||||
|
||||
|
||||
|
||||
+20
@@ -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
|
||||
+291
@@ -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>
|
||||
+20
@@ -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
|
||||
+299
@@ -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>
|
||||
+318
@@ -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);
|
||||
}
|
||||
|
||||
Vendored
+2
@@ -0,0 +1,2 @@
|
||||
#include "stdafx.h"
|
||||
|
||||
Vendored
+11
@@ -0,0 +1,11 @@
|
||||
#pragma once
|
||||
|
||||
#ifdef NDEBUG
|
||||
# define _SECURE_SCL 0
|
||||
#endif
|
||||
|
||||
#include "../../relacy/pch.hpp"
|
||||
|
||||
#include <sstream>
|
||||
|
||||
|
||||
+20
@@ -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
|
||||
+208
@@ -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>
|
||||
+20
@@ -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
|
||||
+207
@@ -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>
|
||||
include/icsneo/third-party/concurrentqueue/tests/relacy/relacy/example/ref_counting/ref_counting.cpp
Vendored
+269
@@ -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;
|
||||
}
|
||||
|
||||
Vendored
+2
@@ -0,0 +1,2 @@
|
||||
#include "stdafx.h"
|
||||
|
||||
Vendored
+8
@@ -0,0 +1,8 @@
|
||||
#pragma once
|
||||
|
||||
#ifdef NDEBUG
|
||||
# define _SECURE_SCL 0
|
||||
#endif
|
||||
|
||||
#include "../../relacy/pch.hpp"
|
||||
|
||||
+11
@@ -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}
|
||||
+20
@@ -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
|
||||
Vendored
+199
@@ -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>
|
||||
+20
@@ -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
|
||||
Vendored
+199
@@ -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>
|
||||
+189
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
+2
@@ -0,0 +1,2 @@
|
||||
#include "stdafx.h"
|
||||
|
||||
+10
@@ -0,0 +1,10 @@
|
||||
#pragma once
|
||||
|
||||
#ifdef NDEBUG
|
||||
# define _SECURE_SCL 0
|
||||
#endif
|
||||
|
||||
#define RL_MSVC_OUTPUT
|
||||
|
||||
#include "../../relacy/pch.hpp"
|
||||
|
||||
+20
@@ -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
|
||||
+207
@@ -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>
|
||||
+20
@@ -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
|
||||
+200
@@ -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>
|
||||
Vendored
+202
@@ -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>();
|
||||
}
|
||||
|
||||
Vendored
+2
@@ -0,0 +1,2 @@
|
||||
#include "stdafx.h"
|
||||
|
||||
+13
@@ -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"
|
||||
|
||||
|
||||
|
||||
Vendored
+2
@@ -0,0 +1,2 @@
|
||||
lock-free stack
|
||||
code contains several bugs: access to freed memory and ABA problem
|
||||
Vendored
+20
@@ -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
|
||||
Vendored
+201
@@ -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>
|
||||
Vendored
+20
@@ -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
|
||||
Vendored
+196
@@ -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>
|
||||
+105
@@ -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>();
|
||||
}
|
||||
|
||||
+2
@@ -0,0 +1,2 @@
|
||||
#include "stdafx.h"
|
||||
|
||||
+8
@@ -0,0 +1,8 @@
|
||||
#pragma once
|
||||
|
||||
#ifdef NDEBUG
|
||||
# define _SECURE_SCL 0
|
||||
#endif
|
||||
|
||||
#include "../../relacy/pch.hpp"
|
||||
|
||||
include/icsneo/third-party/concurrentqueue/tests/relacy/relacy/example/tbb_eventcount/eventcount.cpp
Vendored
+842
@@ -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);
|
||||
}
|
||||
|
||||
+20
@@ -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
|
||||
+203
@@ -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>
|
||||
+20
@@ -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
|
||||
+203
@@ -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>
|
||||
Vendored
+8
@@ -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
|
||||
Vendored
+6
@@ -0,0 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
|
||||
#include "../../relacy/pch.hpp"
|
||||
#include "../../relacy/relacy_std.hpp"
|
||||
|
||||
Vendored
+20
@@ -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
|
||||
+205
@@ -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>
|
||||
Vendored
+20
@@ -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
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user