Stub out the core async-safe list data structure and API.

Issue: PLCR-575
This commit is contained in:
Landon Fuller 2015-07-07 16:33:11 -06:00
Родитель d708c823f5
Коммит b658ab77d6
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 28BBCFC35B80A3C4
3 изменённых файлов: 284 добавлений и 5 удалений

Просмотреть файл

@ -557,6 +557,13 @@
05D0AE301B45EE3C00296632 /* XCTestRunner.mm in Sources */ = {isa = PBXBuildFile; fileRef = 05D0AE2D1B45EE0900296632 /* XCTestRunner.mm */; };
05D0AE421B4B1EBF00296632 /* async_stl.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 05D0AE411B4B1EBF00296632 /* async_stl.hpp */; };
05D0AE431B4B1EBF00296632 /* async_stl.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 05D0AE411B4B1EBF00296632 /* async_stl.hpp */; };
05D0AE511B4C744300296632 /* AsyncList.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 05D0AE491B4C744300296632 /* AsyncList.hpp */; };
05D0AE521B4C744300296632 /* AsyncList.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 05D0AE491B4C744300296632 /* AsyncList.hpp */; };
05D0AE531B4C744300296632 /* AsyncList.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 05D0AE491B4C744300296632 /* AsyncList.hpp */; };
05D0AE541B4C744300296632 /* AsyncList.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 05D0AE491B4C744300296632 /* AsyncList.hpp */; };
05D0AE561B4C7B1400296632 /* AsyncListTests.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 05D0AE551B4C7B1400296632 /* AsyncListTests.cpp */; };
05D0AE571B4C7B1400296632 /* AsyncListTests.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 05D0AE551B4C7B1400296632 /* AsyncListTests.cpp */; };
05D0AE581B4C7B1400296632 /* AsyncListTests.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 05D0AE551B4C7B1400296632 /* AsyncListTests.cpp */; };
05D8FE4C16ACAA6E000ED70C /* AsyncAllocator.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 05D8FE4B16ACAA6E000ED70C /* AsyncAllocator.cpp */; };
05D8FE4D16ACAA6E000ED70C /* AsyncAllocator.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 05D8FE4B16ACAA6E000ED70C /* AsyncAllocator.cpp */; };
05D8FE4E16ACAA6E000ED70C /* AsyncAllocator.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 05D8FE4B16ACAA6E000ED70C /* AsyncAllocator.cpp */; };
@ -1375,6 +1382,8 @@
05D0AE2D1B45EE0900296632 /* XCTestRunner.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = XCTestRunner.mm; sourceTree = "<group>"; };
05D0AE411B4B1EBF00296632 /* async_stl.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = async_stl.hpp; sourceTree = "<group>"; };
05D0AE471B4B2F6E00296632 /* PLCrashCatchTest.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; name = PLCrashCatchTest.hpp; path = "Other Sources/PLCrashCatchTest.hpp"; sourceTree = SOURCE_ROOT; };
05D0AE491B4C744300296632 /* AsyncList.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = AsyncList.hpp; sourceTree = "<group>"; };
05D0AE551B4C7B1400296632 /* AsyncListTests.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = AsyncListTests.cpp; sourceTree = "<group>"; };
05D8FE4B16ACAA6E000ED70C /* AsyncAllocator.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = AsyncAllocator.cpp; sourceTree = "<group>"; };
05D8FE5316ACAA81000ED70C /* AsyncAllocator.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = AsyncAllocator.hpp; sourceTree = "<group>"; };
05D8FE5716ACC8CD000ED70C /* AsyncAllocatorTests.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = AsyncAllocatorTests.mm; sourceTree = "<group>"; };
@ -1856,14 +1865,16 @@
name = Platforms;
sourceTree = "<group>";
};
05A5E28517C0411F008A75E5 /* Linked List */ = {
05A5E28517C0411F008A75E5 /* Data Structures */ = {
isa = PBXGroup;
children = (
05D0AE491B4C744300296632 /* AsyncList.hpp */,
05D0AE551B4C7B1400296632 /* AsyncListTests.cpp */,
05A5E28717C04188008A75E5 /* PLCrashAsyncLinkedList.hpp */,
05A5E28617C04188008A75E5 /* PLCrashAsyncLinkedList.cpp */,
05A5E29317C056EB008A75E5 /* PLCrashAsyncLinkedListTests.mm */,
);
name = "Linked List";
name = "Data Structures";
sourceTree = "<group>";
};
05B929E517C9333800B051E3 /* ObjC Exception Handler */ = {
@ -2023,7 +2034,7 @@
0576DA741B3DC1CD000BCA73 /* Locking */,
05D8FE4916ACAA44000ED70C /* Allocator */,
0576DACD1B42F329000BCA73 /* Reference Counting */,
05A5E28517C0411F008A75E5 /* Linked List */,
05A5E28517C0411F008A75E5 /* Data Structures */,
05BB4CA0166D40B90075171B /* Memory Objects */,
05BB4C9F166D40AD0075171B /* Symbolication */,
05BB4C9D166D3BE10075171B /* Mach-O ABI */,
@ -2440,6 +2451,7 @@
0576DAA91B3E0856000BCA73 /* AsyncAllocatable.hpp in Headers */,
05102E2617B2B80A00B5D925 /* PLCrashHostInfo.h in Headers */,
051F067C17B6B0D4006D0EFA /* PLCrashMachExceptionPort.h in Headers */,
05D0AE531B4C744300296632 /* AsyncList.hpp in Headers */,
05BEC41917BAF92A0082CBFB /* PLCrashMachExceptionPortSet.h in Headers */,
05BEC43817BF1CB10082CBFB /* PLCrashReporterConfig.h in Headers */,
05A5E29117C04188008A75E5 /* PLCrashAsyncLinkedList.hpp in Headers */,
@ -2499,6 +2511,7 @@
0576DAAA1B3E0856000BCA73 /* AsyncAllocatable.hpp in Headers */,
05102E2717B2B80A00B5D925 /* PLCrashHostInfo.h in Headers */,
051F067D17B6B0D4006D0EFA /* PLCrashMachExceptionPort.h in Headers */,
05D0AE541B4C744300296632 /* AsyncList.hpp in Headers */,
05BEC41A17BAF92A0082CBFB /* PLCrashMachExceptionPortSet.h in Headers */,
05BEC43917BF1CB10082CBFB /* PLCrashReporterConfig.h in Headers */,
05A5E29217C04188008A75E5 /* PLCrashAsyncLinkedList.hpp in Headers */,
@ -2534,6 +2547,7 @@
05F3CD7416DFC744007911FB /* PLCrashAsyncCompactUnwindEncoding.h in Headers */,
0576DA8F1B3DC81B000BCA73 /* AsyncPageAllocator.hpp in Headers */,
05E748AE17616D30009B8745 /* dwarf_stack.hpp in Headers */,
05D0AE511B4C744300296632 /* AsyncList.hpp in Headers */,
05C76DAD176B8C7000E9B10D /* dwarf_opstream.hpp in Headers */,
05C76DCF176FBAF300E9B10D /* PLCrashAsyncDwarfCFAState.hpp in Headers */,
0576DAFF1B430285000BCA73 /* PLCrashAsyncDynamicLoader.h in Headers */,
@ -2606,6 +2620,7 @@
05E748AF17616D30009B8745 /* dwarf_stack.hpp in Headers */,
05C76DAE176B8C7000E9B10D /* dwarf_opstream.hpp in Headers */,
05C76DD0176FBAF300E9B10D /* PLCrashAsyncDwarfCFAState.hpp in Headers */,
05D0AE521B4C744300296632 /* AsyncList.hpp in Headers */,
05920D26177B9257001E8975 /* PLCrashFrameDWARFUnwind.h in Headers */,
05102E1617B0151000B5D925 /* PLCrashProcessInfo.h in Headers */,
0576DAB61B41CCE0000BCA73 /* PLCrashAsyncAllocator.h in Headers */,
@ -3287,6 +3302,7 @@
0576DAFC1B430285000BCA73 /* PLCrashAsyncDynamicLoader.cpp in Sources */,
0518E0AA174E8A1F00BB47DE /* PLCrashAsyncDwarfEncoding.cpp in Sources */,
05E74851175E5349009B8745 /* PLCrashAsyncDwarfPrimitives.cpp in Sources */,
05D0AE561B4C7B1400296632 /* AsyncListTests.cpp in Sources */,
05E74856175E5370009B8745 /* PLCrashAsyncDwarfPrimitivesTests.mm in Sources */,
05E748631760D64D009B8745 /* PLCrashAsyncDwarfFDE.cpp in Sources */,
05E7486B1760D891009B8745 /* PLCrashAsyncDwarfCIE.cpp in Sources */,
@ -3372,6 +3388,7 @@
C2198DDE1640188C006EB46A /* PLCrashAsyncObjCSection.mm in Sources */,
C2198DE516402B8A006EB46A /* PLCrashAsyncObjCSectionTests.m in Sources */,
C260228B1642FCA6007FC29F /* PLCrashAsyncSymbolication.c in Sources */,
05D0AE571B4C7B1400296632 /* AsyncListTests.cpp in Sources */,
0576DAEE1B42F387000BCA73 /* shared_ptr_test.cpp in Sources */,
C26022911642FE9B007FC29F /* PLCrashAsyncSymbolicationTests.m in Sources */,
C2198E0B16441CF5006EB46A /* PLCrashAsyncMachOString.c in Sources */,
@ -3517,6 +3534,7 @@
0576DAFE1B430285000BCA73 /* PLCrashAsyncDynamicLoader.cpp in Sources */,
05659DF417456A4000D2EE21 /* PLCrashAsyncDwarfEncodingTests.mm in Sources */,
05659DFB174D2E1200D2EE21 /* PLCrashTestCase.m in Sources */,
05D0AE581B4C7B1400296632 /* AsyncListTests.cpp in Sources */,
0518E0A9174E8A1300BB47DE /* PLCrashAsyncDwarfEncoding.cpp in Sources */,
05E74853175E5349009B8745 /* PLCrashAsyncDwarfPrimitives.cpp in Sources */,
05E74858175E5370009B8745 /* PLCrashAsyncDwarfPrimitivesTests.mm in Sources */,
@ -4624,7 +4642,7 @@
buildSettings = {
CLANG_CXX_LANGUAGE_STANDARD = "c++0x";
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
CURRENT_PROJECT_VERSION = "1.2.1";
CURRENT_PROJECT_VERSION = 1.2.1;
GCC_C_LANGUAGE_STANDARD = c99;
GCC_ENABLE_CPP_EXCEPTIONS = NO;
GCC_ENABLE_CPP_RTTI = NO;
@ -4667,7 +4685,7 @@
buildSettings = {
CLANG_CXX_LANGUAGE_STANDARD = "c++0x";
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
CURRENT_PROJECT_VERSION = "1.2.1";
CURRENT_PROJECT_VERSION = 1.2.1;
GCC_C_LANGUAGE_STANDARD = c99;
GCC_ENABLE_CPP_EXCEPTIONS = NO;
GCC_ENABLE_CPP_RTTI = NO;

173
Source/AsyncList.hpp Normal file
Просмотреть файл

@ -0,0 +1,173 @@
/*
* Author: Landon Fuller <landonf@plausible.coop>
*
* Copyright (c) 2015 Plausible Labs Cooperative, Inc.
* All rights reserved.
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following
* conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef PLCRASH_ASYNC_LINKED_LIST_HPP
#define PLCRASH_ASYNC_LINKED_LIST_HPP 1
#include "PLCrashMacros.h"
#include "AsyncAllocator.hpp"
#include "AsyncAllocatable.hpp"
#include "shared_ptr.hpp"
#include "async_stl.hpp"
PLCR_CPP_BEGIN_ASYNC_NS
/**
* @internal
* @ingroup plcrash_async
*
* An async-safe immutable list.
*
* @tparam T The list element type.
*/
template<typename T> class List : public AsyncAllocatable {
private:
/**
* A 'cons' cell containing an initial ('head') value, and a tail reference.
*/
struct Cons : public AsyncAllocatable {
/**
* Construct a cell with both a head and a tail.
*
* @param head The initial element.
* @param tail A reference to the tail elements.
*/
Cons (T head, shared_ptr<const Cons> tail) : _head(head), _tail(atl::move(tail)) {}
/**
* Construct a single element cell with an empty list tail.
*
* @param head The single element to be included in this cell.
*/
explicit Cons (T head) : _head(head) {}
/** The cell's value. */
T _head;
/** The tail reference; may be NULL. */
shared_ptr<const Cons> _tail;
};
/**
* Construct a new list with a reference to an existing list's backing cons cell.
*
* @param cons An existing cons cell representing the list.
*/
explicit List (shared_ptr<const Cons> cons) : _head(atl::move(cons)) {}
public:
/**
* Construct an empty list.
*/
constexpr List () : _size(0) {}
/**
* Construct a single element list.
*
* @param allocator The allocator to be used for any internal allocations when constructing the list.
* @param head The first (and only) element of the returned list.
*/
List (AsyncAllocator *allocator, T head) : _head(make_shared<const Cons>(allocator, head)), _size(1) {}
/**
* Construct a list containing @a head, followed by @a tail.
*
* @param allocator The allocator to be used for any internal allocations when constructing the list.
* @param head The first element of the returned list.
* @param tail The tail elements of the returned list.
*/
List (AsyncAllocator *allocator, T head, List const &tail) : _head(make_shared<const Cons>(allocator, head, tail._head)), _size(tail._size + 1) {}
/** Copy constructor */
List (const List &other) = default;
/** Move constructor */
List (List &&other) = default;
/** Copy assignment operator */
List &operator =(const List &other) = default;
/** Move assignment operator */
List &operator =(List &&other) = default;
/**
* Return true if this list is empty, false otherwise.
*/
bool isEmpty () const { return !_head; }
/**
* Return the first value in the list. The behavior of this method on empty lists
* is undefined.
*/
T head () const {
return _head->_head;
}
/**
* Return the list tail.
*/
List tail () const {
/* If empty, no need to construct a new list. */
if (isEmpty()) {
return *this;
} else {
return List(_head->_tail);
}
}
/**
* Return a new list with the given value prepended to this list.
*
* @param allocator The allocator to be used for any internal allocations when constructing the new list.
* @param value The value to prepend.
*/
List prepend (AsyncAllocator *allocator, T value) {
return List(allocator, value, *this);
}
/**
* Return the number of elements in this list.
*/
size_t size () { return _size; }
private:
/** The first cell of this list, or an empty (NULL) value. */
shared_ptr<const Cons> _head;
/** The size of the list accessible via _head */
size_t _size;
};
PLCR_CPP_END_ASYNC_NS
#endif /* PLCRASH_ASYNC_LINKED_LIST_HPP */

88
Source/AsyncListTests.cpp Normal file
Просмотреть файл

@ -0,0 +1,88 @@
/*
* Copyright (c) 2014 - 2015 Plausible Labs Cooperative, Inc.
* All rights reserved.
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following
* conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
#include "shared_ptr.hpp"
#include "weak_ptr.hpp"
#include "PLCrashCatchTest.hpp"
#include "AsyncList.hpp"
PLCR_CPP_BEGIN_ASYNC_NS
TEST_CASE("AsyncList") {
AsyncAllocator *allocator;
REQUIRE(AsyncAllocator::Create(&allocator, PAGE_SIZE) == PLCRASH_ESUCCESS);
WHEN("constructing an empty list") {
List<int> l;
REQUIRE(l.size() == 0);
REQUIRE(l.isEmpty());
THEN("the tail should also be empty") {
REQUIRE(l.tail().isEmpty());
}
}
WHEN("constructing a single-element list") {
List<int> l(allocator, 42);
REQUIRE(l.size() == 1);
REQUIRE(!l.isEmpty());
THEN("the tail should be empty") {
REQUIRE(l.tail().isEmpty());
}
}
WHEN("prepending an element") {
WHEN("the list is empty") {
List<int> l;
auto prepended = l.prepend(allocator, 42);
REQUIRE(prepended.head() == 42);
REQUIRE(prepended.size() == 1);
REQUIRE(prepended.tail().isEmpty());
}
WHEN("the list is not empty") {
List<int> l(allocator, 42);
auto prepended = l.prepend(allocator, 84);
REQUIRE(prepended.head() == 84);
REQUIRE(prepended.size() == 2);
REQUIRE(!prepended.tail().isEmpty());
REQUIRE(prepended.tail().head() == 42);
}
}
/* Clean up */
delete allocator;
}
PLCR_CPP_END_ASYNC_NS