Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Eliminate platform-specific interlocked routines #982

Merged
merged 2 commits into from Aug 18, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/autonet/AutoNetServerImpl.cpp
Expand Up @@ -200,7 +200,7 @@ void AutoNetServerImpl::NewObject(CoreContext& ctxt, const CoreObjectDescriptor&
// Add slots for this object
{
Json::array slots;
for(auto slot = object.stump->pHead; slot; slot = slot->pFlink) {
for(const SlotInformation* slot = object.stump->pHead; slot; slot = slot->pFlink) {
slots.push_back(Json::object{
{"id", autowiring::demangle(slot->type)},
{"autoRequired", slot->autoRequired},
Expand Down
13 changes: 0 additions & 13 deletions src/autowiring/CMakeLists.txt
Expand Up @@ -123,7 +123,6 @@ set(Autowiring_SRCS
HeteroBlock.h
HeteroBlock.cpp
index_tuple.h
InterlockedExchange.h
is_any.h
is_shared_ptr.h
ManualThreadPool.h
Expand Down Expand Up @@ -215,7 +214,6 @@ add_windows_sources(Autowiring_SRCS
SystemThreadPoolWinXP.hpp
SystemThreadPoolWinLH.cpp
SystemThreadPoolWinLH.hpp
InterlockedExchangeWin.cpp
thread_specific_ptr_win.cpp
)

Expand All @@ -226,7 +224,6 @@ add_mac_sources(Autowiring_SRCS

add_unix_sources(Autowiring_SRCS
CreationRulesUnix.cpp
InterlockedExchangeUnix.cpp
thread_specific_ptr_unix.cpp
)

Expand All @@ -236,16 +233,6 @@ set(Autowiring_Linux_SRCS

add_conditional_sources(Autowiring_SRCS "NOT MSVC" GROUP_NAME "Non-Windows Source" FILES ${Autowiring_Unix_SRCS})

add_conditional_sources(
Autowiring_SRCS "WIN32 AND standard_BUILD_ARCHITECTURES EQUAL x86"
GROUP_NAME "ASMx86 Source"
FILES interlocked.asm
)

if(WIN32 AND standard_BUILD_ARCHITECTURES EQUAL "x86")
enable_language(ASM_MASM)
endif()

add_conditional_sources(
Autowiring_SRCS
"NOT WIN32 AND NOT APPLE"
Expand Down
2 changes: 1 addition & 1 deletion src/autowiring/CoreContext.cpp
Expand Up @@ -102,7 +102,7 @@ CoreContext::~CoreContext(void) {
uint8_t* pBase = (uint8_t*)ccType.value.ptr();

// Enumerate all slots and unlink them one at a time
for (auto cur = ccType.stump->pHead; cur; cur = cur->pFlink) {
for (const SlotInformation* cur = ccType.stump->pHead; cur; cur = cur->pFlink) {
if (cur->autoRequired)
// Only unlink slots that were Autowired. AutoRequired slots will never participate
// in a cycle (because we would wind up with constructive chaos) so we don't really
Expand Down
28 changes: 0 additions & 28 deletions src/autowiring/InterlockedExchange.h

This file was deleted.

15 changes: 0 additions & 15 deletions src/autowiring/InterlockedExchangeUnix.cpp

This file was deleted.

24 changes: 0 additions & 24 deletions src/autowiring/InterlockedExchangeWin.cpp

This file was deleted.

23 changes: 9 additions & 14 deletions src/autowiring/SlotInformation.cpp
Expand Up @@ -2,7 +2,6 @@
#include "stdafx.h"
#include "SlotInformation.h"
#include "AutowirableSlot.h"
#include "InterlockedExchange.h"
#include "thread_specific_ptr.h"
#include MEMORY_HEADER

Expand All @@ -20,23 +19,19 @@ SlotInformationStackLocation::SlotInformationStackLocation(SlotInformationStumpB
tss.reset(this);
}

template<class T>
void UpdateOrCascadeDelete(T* ptr, const T*& dest) {
if(!compare_exchange<T>(&dest, ptr, nullptr))
// Exchange passed, the destination now owns this pointer
return;

// Failed the exchange, return here
std::unique_ptr<const T> prior;
for(const auto* cur = ptr; cur; cur = cur->pFlink)
prior.reset(cur);
}

SlotInformationStackLocation::~SlotInformationStackLocation(void) {
// Replace the prior stack location, we were pushed
tss.reset(&prior);

UpdateOrCascadeDelete(m_pCur, stump.pHead);
const SlotInformation* p = nullptr;
if (!stump.pHead.compare_exchange_strong(p, m_pCur, std::memory_order_acquire)) {
// Failed the exchange, destroy
std::unique_ptr<SlotInformation> prior;
for (const auto* cur = m_pCur; cur; cur = cur->pFlink)
prior.reset(m_pCur);
}
///else
// Exchange passed, the destination now owns this pointer

// Unconditionally update to true, no CAS needed
stump.bInitialized = true;
Expand Down
7 changes: 5 additions & 2 deletions src/autowiring/SlotInformation.h
Expand Up @@ -2,6 +2,7 @@
#pragma once
#include "auto_id.h"
#include "TypeUnifier.h"
#include <atomic>
#include <typeinfo>
#include MEMORY_HEADER

Expand Down Expand Up @@ -39,7 +40,9 @@ struct SlotInformation {
struct SlotInformationStumpBase {
SlotInformationStumpBase(const std::type_info& ti) :
ti(ti)
{}
{
pHead = nullptr;
}

// RTTI to which this stump pertains
const std::type_info& ti;
Expand All @@ -48,7 +51,7 @@ struct SlotInformationStumpBase {
bool bInitialized = false;

// Current slot information:
const SlotInformation* pHead = nullptr;
std::atomic<const SlotInformation*> pHead;
};

/// <summary>
Expand Down
15 changes: 7 additions & 8 deletions src/autowiring/TeardownNotifier.cpp
@@ -1,12 +1,13 @@
// Copyright (C) 2012-2015 Leap Motion, Inc. All rights reserved.
#include "stdafx.h"
#include "TeardownNotifier.h"
#include "InterlockedExchange.h"

using namespace autowiring;

TeardownNotifier::TeardownNotifier(void)
{}
{
m_pFirstTeardownListener = nullptr;
}

TeardownNotifier::~TeardownNotifier(void) {
// Notify all teardown listeners, this will be our last opportunity to do so:
Expand All @@ -15,7 +16,7 @@ TeardownNotifier::~TeardownNotifier(void) {

void TeardownNotifier::NotifyTeardownListeners(void) {
EntryBase* next;
for (auto cur = m_pFirstTeardownListener; cur; cur = next) {
for (EntryBase* cur = m_pFirstTeardownListener; cur; cur = next) {
next = cur->pFlink;
(*cur)();
delete cur;
Expand All @@ -25,9 +26,7 @@ void TeardownNotifier::NotifyTeardownListeners(void) {
}

void TeardownNotifier::AddTeardownListenerInternal(EntryBase* listener) {
EntryBase* pResult;
do {
listener->pFlink = m_pFirstTeardownListener;
pResult = compare_exchange<EntryBase>(&m_pFirstTeardownListener, listener, listener->pFlink);
} while (pResult != listener->pFlink);
EntryBase* priorHead = m_pFirstTeardownListener;
while (!m_pFirstTeardownListener.compare_exchange_weak(priorHead, listener))
listener->pFlink = priorHead;
}
3 changes: 2 additions & 1 deletion src/autowiring/TeardownNotifier.h
@@ -1,6 +1,7 @@
// Copyright (C) 2012-2015 Leap Motion, Inc. All rights reserved.
#pragma once
#include "C++11/cpp11.h"
#include <atomic>
#include RVALUE_HEADER

namespace autowiring {
Expand Down Expand Up @@ -38,7 +39,7 @@ class TeardownNotifier
};

// Teardown listeners, invoked in sequence when the context is tearing down
EntryBase* m_pFirstTeardownListener = nullptr;
std::atomic<EntryBase*> m_pFirstTeardownListener;

/// <summary>
/// May be invoked prospectively by a derived instance to prematurely notify teardown listeners
Expand Down
11 changes: 0 additions & 11 deletions src/autowiring/interlocked.asm

This file was deleted.

1 change: 0 additions & 1 deletion src/autowiring/test/CMakeLists.txt
Expand Up @@ -47,7 +47,6 @@ set(AutowiringTest_SRCS
GlobalInitTest.hpp
GlobalInitTest.cpp
HeteroBlockTest.cpp
InterlockedRoutinesTest.cpp
MarshallerTest.cpp
MultiInheritTest.cpp
ObjectPoolTest.cpp
Expand Down
8 changes: 4 additions & 4 deletions src/autowiring/test/ContextMemberTest.cpp
Expand Up @@ -59,7 +59,7 @@ TEST_F(ContextMemberTest, VerifyDetectedMembers)
// Validate all pointers are what we expect to find, and in the right order
size_t ct = 0;

for(auto cur = SlotInformationStump<HasAFewSlots>::s_stump.pHead; cur; cur = cur->pFlink) {
for(const SlotInformation* cur = SlotInformationStump<HasAFewSlots>::s_stump.pHead; cur; cur = cur->pFlink) {
// Validate slot types:
ASSERT_EQ(expected[ct].type, cur->type) << "Slot number " << ct << " had a mismatched type";
ASSERT_EQ(expected[ct].slotOffset, cur->slotOffset) << "Slot number " << ct << " had a mismatched offset";
Expand All @@ -81,14 +81,14 @@ TEST_F(ContextMemberTest, RecursiveRelationshipNoContextMember) {

// Now verify that we only get the type we expect, and none of the transitive types:
size_t ct = 0;
for(auto cur = SlotInformationStump<AutoRequiresSomething>::s_stump.pHead; cur; cur = cur->pFlink)
for(const SlotInformation* cur = SlotInformationStump<AutoRequiresSomething>::s_stump.pHead; cur; cur = cur->pFlink)
ct++;
ASSERT_LE(1UL, ct) << "Recursive construction of an AutoRequired type incorrectly mapped in slots in a created field";
ASSERT_GE(ct, 1UL) << "Recursive construction failed to map a type after an AutoRequired field was constructed";

// Descendant type should also be correctly initialized:
ct = 0;
for(auto cur = SlotInformationStump<HasAFewSlots>::s_stump.pHead; cur; cur = cur->pFlink)
for(const SlotInformation* cur = SlotInformationStump<HasAFewSlots>::s_stump.pHead; cur; cur = cur->pFlink)
ct++;
ASSERT_EQ(3UL, ct) << "Recursively AutoRequired type did not enumerate all of the expected slots upon reflection";
}
Expand All @@ -109,7 +109,7 @@ TEST_F(ContextMemberTest, TransientAutowiring) {
AutoRequired<AutowiresInCtor> aictor;

size_t ct = 0;
for(auto cur = SlotInformationStump<AutowiresInCtor>::s_stump.pHead; cur; cur = cur->pFlink)
for(const SlotInformation* cur = SlotInformationStump<AutowiresInCtor>::s_stump.pHead; cur; cur = cur->pFlink)
ct++;

ASSERT_EQ(1UL, ct) << "An autowirable slot declared on the stack was incorrectly detected as being a type member";
Expand Down