Skip to content

Commit

Permalink
Validated against Clang/libc++ 3.9
Browse files Browse the repository at this point in the history
  • Loading branch information
hsutter committed Oct 16, 2016
1 parent a16101e commit ad9fe3c
Show file tree
Hide file tree
Showing 4 changed files with 13 additions and 15 deletions.
15 changes: 10 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
# **gcpp**: Deferred and unordered destruction

Herb Sutter -- Updated 2016-09-26
Herb Sutter -- Updated 2016-10-16

## Motivation, goals, and disclaimers

gcpp is a personal project to try an experiment: Can we take the deferred and unordered destruction patterns with custom reachability tracing logic that we find ourselves writing by hand today, and automate some parts of that work as a reusable C++ library that delivers it as a zero-overhead abstraction?

This is a demo of a potential additional fallback option for the rare cases where `unique_ptr` and `shared_ptr` aren't quite enough, notably when you have objects that refer to each other in local owning cycles, or when you need to defer destructor execution to meet real-time deadlines or to bound destructor stack cost. The goal is to illustrate ideas that others can draw from, that you may find useful even if you never use types like the ones below but just continue to use existing smart pointers and write your destructor-deferral and tracing code by hand.

Disclaimers: This is a demo, not a production quality library. It is not thoroughly tested; bug reports are welcome. As of this writing, I have only tried it on one compiler and STL implementation, Visual Studio 2015 Update 3 (`deferred_allocator` does not work on Update 2 which had only partial support for C++11 allocators with fancy pointers); if you have success with others, please report it by opening an Issue to update this README. See also the FAQ ["So deferred_heap and deferred_ptr have no disadvantages?"](#q-so-deferred_heap-and-deferred_ptr-have-no-disadvantages). And please see the [Acknowledgments](#acknowledgments).
Disclaimers: This is a demo, not a production quality library; bug reports are welcome. As of this writing, it works on Clang/libc++ 3.9 or later and Visual Studio 2015 Update 3 or later; if you have success with others, please report it by opening an Issue to update this README. See also the FAQ ["So deferred_heap and deferred_ptr have no disadvantages?"](#q-so-deferred_heap-and-deferred_ptr-have-no-disadvantages). And please see the [Acknowledgments](#acknowledgments).

## Overview

Expand Down Expand Up @@ -99,7 +99,7 @@ public:
};
~~~

Note that `deferred_allocator` requires C++11 allocator support for fancy pointers; on MSVC, it requires Visual Studio 2015 Update 3 or later.
Note that `deferred_allocator` requires C++11 allocator support for fancy pointers; see [deferred_allocator implementation notes](#deferred-allocator-notes).

## Target use cases

Expand Down Expand Up @@ -288,9 +288,14 @@ One line removes the type, and the other line adds it back. The lambda gives a h
A non-capturing lambda has no state, so it can be used as a plain function. So for each distinct type `T` that this is instantiated with, compiling this code generates one `T`-specific function (on demand at compile time, globally unique) and we store that function's address. The function itself is efficient: Depending on the optimization level, the lambda is typically generated as either a one-instruction wrapper function (just a single `jmp` to the actual destructor) or as a copy of the destructor if the destructor is inlined (no run-time overhead at all, just another inline copy of the destructor in the binary if it's generally being inlined anyway).


## deferred_allocator
## deferred_allocator notes

`deferred_allocator` appears to work with unmodified current STL containers, but I'm still exploring how well and exploring the limits.
`deferred_allocator` appears to work with unmodified C++11-conforming STL containers.

- It requires good support for C++11 fancy pointers.
- On Microsoft VC++, it requires Visual Studio 2015 Update 3 or later. Update 2 in known to have inadequate fancy pointer support.
- On Clang/libc++, it requires version 3.9 or later. It might work on 3.7 or 3.8 which I didn't test, but 3.6 is known to have inadequate fancy pointer support (fails to call `construct()`).
- I haven't found a version of GCC that supports it yet.

- `deallocate()` is a no-op, but performs checking in debug builds. It does not need to actually deallocate because memory-safe deallocation will happen at the next `.collect()` after the memory becomes unreachable.

Expand Down
7 changes: 0 additions & 7 deletions deferred_allocator.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,13 +30,6 @@

namespace gcpp {

//private:
//namespace detail {
// deferred_heap& global_deferred_heap();
//}

//public:

//----------------------------------------------------------------------------
//
// deferred_allocator - wrap up global_deferred_heap() as a C++14 allocator, with thanks to
Expand Down
2 changes: 1 addition & 1 deletion deferred_heap.h
Original file line number Diff line number Diff line change
Expand Up @@ -917,7 +917,7 @@ namespace gcpp {
template<class T>
void deferred_heap::destroy(gsl::not_null<T*> p) noexcept
{
Expects((p == nullptr || dtors.is_stored(p))
Expects(dtors.is_stored(p)
&& "attempt to destroy an object whose destructor is not registered");
}

Expand Down
4 changes: 2 additions & 2 deletions test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -440,7 +440,7 @@ void test_bitflags() {

int main() {
//test_page();
test_bitflags();
//test_bitflags();

//test_deferred_heap();
//time_deferred_heap();
Expand All @@ -450,7 +450,7 @@ int main() {
//test_deferred_allocator_set();
//time_deferred_allocator_set();

//test_deferred_allocator_vector();
test_deferred_allocator_vector();
//time_deferred_allocator_vector();

//test_deferred_array();
Expand Down

0 comments on commit ad9fe3c

Please sign in to comment.