Updated with README and stuff.
This commit is contained in:
		
							parent
							
								
									27d16e33bd
								
							
						
					
					
						commit
						9635a253f5
					
				| 
						 | 
				
			
			@ -1,7 +1,6 @@
 | 
			
		|||
project("Collector")
 | 
			
		||||
 | 
			
		||||
list(APPEND CMAKE_C_FLAGS "-std=c99 ${CMAKE_C_FLAGS} -g -ftest-coverage -fprofile-arcs")
 | 
			
		||||
list(APPEND CMAKE_CXX_FLAGS "${CXXMAKE_C_FLAGS} -std=c++1y -I../src/include/ -g")
 | 
			
		||||
 | 
			
		||||
add_executable(collector
 | 
			
		||||
    src/collector.c)
 | 
			
		||||
add_executable(collector src/collector.cpp)
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -0,0 +1,65 @@
 | 
			
		|||
---
 | 
			
		||||
**WHAT:**
 | 
			
		||||
 | 
			
		||||
This is an example of Bob Nystrom's
 | 
			
		||||
"[Baby's First Garbage Collector](http://journal.stuffwithstuff.com/2013/12/08/babys-first-garbage-collector/),"
 | 
			
		||||
which I've been wanting to implement for a while in order to understand
 | 
			
		||||
it better.  To make the problem harder (as I always do), I decided to
 | 
			
		||||
write it in C++, and to make it even more fun, I've implemented it using
 | 
			
		||||
the new Variant container from C++17.
 | 
			
		||||
 | 
			
		||||
**WHY:**
 | 
			
		||||
 | 
			
		||||
I've never written a garbage collector before.  Now I know what it is
 | 
			
		||||
and how it works.
 | 
			
		||||
 | 
			
		||||
**DETAILS:**
 | 
			
		||||
 | 
			
		||||
The collector Nystrom wrote is a simple bi-color mark-and-sweep
 | 
			
		||||
collector for a singly threaded process with distinct pauses based upon
 | 
			
		||||
a straightforward memory usage heuristic.  That heuristic is simply, "Is
 | 
			
		||||
the amount of memory currently in use twice as much as the last time we
 | 
			
		||||
garbage collected?"  If the answer is yes, the collector runs and sweeps
 | 
			
		||||
up the stack.
 | 
			
		||||
 | 
			
		||||
Nystrom's code is highly readable, and I hope mine is as well.  Because
 | 
			
		||||
I used Variant, my Object class has an internal Pair class, and then the
 | 
			
		||||
Variant is just \<int, Pair\>, where "Pair" is a pair of pointers to
 | 
			
		||||
other objects.  The entirety of the VM is basically a stack of
 | 
			
		||||
singly-linked lists which either represents integers or collections of
 | 
			
		||||
integers in a Lisp-like structure.
 | 
			
		||||
 | 
			
		||||
The allocator creates two kinds of objects, then: pairs, and lists.  A
 | 
			
		||||
pair is created by pushing two other objects onto the stack, then
 | 
			
		||||
calling `push()`, which pops them off the stack and replaces them with a
 | 
			
		||||
Pair object.  The VM class has two methods, both named `push()`, one of
 | 
			
		||||
which pushes an integer, the other a pair.  Since a pair is built from
 | 
			
		||||
objects on the stack, the Pair version takes no arguments, and since
 | 
			
		||||
C++14 and beyond have move semantics that Variant honors,
 | 
			
		||||
Variant\<Pair\> only constructs a single pair.  Pretty nice.  I was also
 | 
			
		||||
able to use both lambda-style and constructor-style visitors in my
 | 
			
		||||
Variant, which was a fun little bonus.
 | 
			
		||||
 | 
			
		||||
**NOTE:**
 | 
			
		||||
 | 
			
		||||
I have included the header files for the
 | 
			
		||||
[Mapbox version of Variant](https://github.com/mapbox/variant) since the
 | 
			
		||||
C++17 committee's standards haven't quite reached the general public and
 | 
			
		||||
the Variant implementation is still a subject of some debate.  This
 | 
			
		||||
implementation looks straightforward enough and is a header-only
 | 
			
		||||
release.  It works with both GCC 4.8.5 and Clang 3.8, and that's good
 | 
			
		||||
enough for me.
 | 
			
		||||
 | 
			
		||||
The Mapbox variant is BSD licensed, and a copy of the license is
 | 
			
		||||
included in the Include directory.
 | 
			
		||||
 | 
			
		||||
**BUILDING:**
 | 
			
		||||
 | 
			
		||||
From the base directory of the project:
 | 
			
		||||
 | 
			
		||||
mkdir build
 | 
			
		||||
cd build
 | 
			
		||||
cmake ..
 | 
			
		||||
make
 | 
			
		||||
 | 
			
		||||
And you should be able to run the basic tests.  It's just one file.
 | 
			
		||||
| 
						 | 
				
			
			@ -37,6 +37,7 @@ public:
 | 
			
		|||
  unsigned char marked;
 | 
			
		||||
  Object *next;
 | 
			
		||||
  Object(int v): marked(0), value(v) {}
 | 
			
		||||
  // Variant<Pair> uses move semantics; this doesn't result in Pair being built twice.
 | 
			
		||||
  Object(Object* head, Object* tail): marked(0), value(Pair(head, tail)) {}
 | 
			
		||||
 | 
			
		||||
  class Pair {
 | 
			
		||||
| 
						 | 
				
			
			@ -113,10 +114,10 @@ public:
 | 
			
		|||
 | 
			
		||||
  /* The saddest fact: I went with using NULL as our end-of-stack
 | 
			
		||||
     discriminator rather than something higher-level, like an
 | 
			
		||||
     Optional or Either-variant, because to use those I'd have to
 | 
			
		||||
     user recursion to sweep the interpreter's stack, which means
 | 
			
		||||
     I'm at the mercy of the C stack, complete with the cost of the
 | 
			
		||||
     unwind at the end.  Bummer. */
 | 
			
		||||
     Optional or Either-variant, because to use those I'd have to use
 | 
			
		||||
     recursion to sweep the interpreter's stack, which means I'm at
 | 
			
		||||
     the mercy of the C stack, complete with the cost of the unwind at
 | 
			
		||||
     the end.  Bummer. */
 | 
			
		||||
 | 
			
		||||
  /* I look at this and ask, WWHSD?  What Would Herb Sutter Do? */
 | 
			
		||||
  
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -0,0 +1,25 @@
 | 
			
		|||
Copyright (c) MapBox
 | 
			
		||||
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.
 | 
			
		||||
- Neither the name "MapBox" nor the names of its contributors may be
 | 
			
		||||
  used to endorse or promote products derived from this software without
 | 
			
		||||
  specific prior written permission.
 | 
			
		||||
 | 
			
		||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 COPYRIGHT HOLDER OR CONTRIBUTORS 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.
 | 
			
		||||
		Loading…
	
		Reference in New Issue