├── .hgignore ├── Makefile ├── README ├── archive ├── include │ ├── condition_variable.h │ ├── cxx11.h │ ├── functional.h │ ├── mutex.h │ ├── posix_errors.h │ ├── system_error.h │ ├── test_mutex.h │ ├── thread.h │ ├── unordered_map.h │ └── unordered_set.h ├── src │ ├── atomic.c │ ├── condition_variable.cc │ ├── mutex.cc │ ├── test_mutex.cc │ └── thread.cc ├── testing │ ├── atomic_cpp_test.cc │ ├── condition_variable_test.cc │ ├── cxx11_test.cc │ ├── lock_test.cc │ ├── test_mutex_test.cc │ └── thread_test.cc └── util │ └── atomic.sh ├── doc └── stream_mutex.html ├── include ├── barrier.h ├── buffer_queue.h ├── closed_error.h ├── concurrent_priority_queue.h ├── countdown_latch.h ├── counter.h ├── debug.h ├── dynarray.h ├── flex_barrier.h ├── gcl_string.h ├── iterator_queue.h ├── latch.h ├── lock_free_buffer_queue.h ├── map_reduce.h ├── map_reduce_helpers.h ├── map_reduce_impl.h ├── mutable_thread.h ├── pipeline.h ├── queue_base.h ├── scoped_guard.h ├── serial_executor.h ├── simple_thread_pool.h ├── source.h └── stream_mutex.h ├── papers ├── latch_barrier.html ├── n3533.html └── pipeline.html ├── samples ├── blackscholes │ ├── Makefile │ ├── blackscholes.cc │ └── input.txt └── dedup │ ├── Makefile │ ├── binheap.c │ ├── binheap.h │ ├── config.h │ ├── debug.h │ ├── decoder.c │ ├── decoder.h │ ├── dedup.c │ ├── dedupdef.h │ ├── encoder.c │ ├── encoder.h │ ├── hashtable.c │ ├── hashtable.h │ ├── hashtable_private.h │ ├── mbuffer.c │ ├── mbuffer.h │ ├── openssl │ ├── LICENSE │ ├── README │ ├── md32_common.h │ ├── sha.h │ └── sha_locl.h │ ├── queue.c │ ├── queue.h │ ├── rabin.c │ ├── rabin.h │ ├── sha.c │ ├── sha.h │ ├── tree.c │ ├── tree.h │ ├── util.c │ └── util.h ├── src ├── barrier.cc ├── countdown_latch.cc ├── debug.cc ├── flex_barrier.cc ├── flex_barrier_test.cc ├── latch.cc ├── mutable_thread.cc ├── serial_executor.cc ├── simple_thread_pool.cc └── stream_mutex.cc ├── testing ├── barrier_test.cc ├── blockable_thread.cc ├── blockable_thread.h ├── buffer_queue_test.cc ├── called_task.h ├── cleanup_assert.h ├── concurrent_priority_queue_test.cc ├── countdown_latch_test.cc ├── counter_test.cc ├── dynarray_test.cc ├── iterator_queue_test.cc ├── latch_test.cc ├── lock_free_buffer_queue_test.cc ├── map_reduce_test.cc ├── mutable_thread_test.cc ├── pipeline_test.cc ├── queue_base_test.h ├── queue_perf_test.cc ├── race_test.cc ├── scoped_guard_test.cc ├── serial_executor_test.cc ├── simple_thread_pool_test.cc ├── source_test.cc └── stream_mutex_test.cc ├── third_party ├── ThreadSanitizer │ ├── Darwin-i386 │ │ └── tsan-self-contained.sh │ ├── Linux-x86_64 │ │ └── tsan-self-contained.sh │ └── README ├── googlemock │ ├── CHANGES │ ├── CONTRIBUTORS │ ├── COPYING │ ├── README │ ├── include │ │ └── gmock │ │ │ ├── gmock-actions.h │ │ │ ├── gmock-cardinalities.h │ │ │ ├── gmock-generated-actions.h │ │ │ ├── gmock-generated-actions.h.pump │ │ │ ├── gmock-generated-function-mockers.h │ │ │ ├── gmock-generated-function-mockers.h.pump │ │ │ ├── gmock-generated-matchers.h │ │ │ ├── gmock-generated-matchers.h.pump │ │ │ ├── gmock-generated-nice-strict.h │ │ │ ├── gmock-generated-nice-strict.h.pump │ │ │ ├── gmock-matchers.h │ │ │ ├── gmock-more-actions.h │ │ │ ├── gmock-printers.h │ │ │ ├── gmock-spec-builders.h │ │ │ ├── gmock.h │ │ │ └── internal │ │ │ ├── gmock-generated-internal-utils.h │ │ │ ├── gmock-generated-internal-utils.h.pump │ │ │ ├── gmock-internal-utils.h │ │ │ └── gmock-port.h │ └── src │ │ ├── gmock-all.cc │ │ ├── gmock-cardinalities.cc │ │ ├── gmock-internal-utils.cc │ │ ├── gmock-matchers.cc │ │ ├── gmock-printers.cc │ │ ├── gmock-spec-builders.cc │ │ ├── gmock.cc │ │ └── gmock_main.cc └── googletest │ ├── CHANGES │ ├── CONTRIBUTORS │ ├── COPYING │ ├── README │ ├── include │ └── gtest │ │ ├── gtest-death-test.h │ │ ├── gtest-message.h │ │ ├── gtest-param-test.h │ │ ├── gtest-param-test.h.pump │ │ ├── gtest-printers.h │ │ ├── gtest-spi.h │ │ ├── gtest-test-part.h │ │ ├── gtest-typed-test.h │ │ ├── gtest.h │ │ ├── gtest_pred_impl.h │ │ ├── gtest_prod.h │ │ └── internal │ │ ├── gtest-death-test-internal.h │ │ ├── gtest-filepath.h │ │ ├── gtest-internal.h │ │ ├── gtest-linked_ptr.h │ │ ├── gtest-param-util-generated.h │ │ ├── gtest-param-util-generated.h.pump │ │ ├── gtest-param-util.h │ │ ├── gtest-port.h │ │ ├── gtest-string.h │ │ ├── gtest-tuple.h │ │ ├── gtest-tuple.h.pump │ │ ├── gtest-type-util.h │ │ └── gtest-type-util.h.pump │ └── src │ ├── gtest-all.cc │ ├── gtest-death-test.cc │ ├── gtest-filepath.cc │ ├── gtest-internal-inl.h │ ├── gtest-port.cc │ ├── gtest-printers.cc │ ├── gtest-test-part.cc │ ├── gtest-typed-test.cc │ ├── gtest.cc │ └── gtest_main.cc ├── util ├── Makefile ├── exetest.sh └── makejobs.sh └── wiki ├── CurrentTaskList.wiki ├── GettingStarted.wiki ├── LatchesAndBarriers.wiki ├── PipelineExecutionFramework.wiki ├── RaceDetectionTools.wiki └── SubmittedProposals.wiki /.hgignore: -------------------------------------------------------------------------------- 1 | syntax: glob 2 | AllTests 3 | *.d 4 | *.o 5 | *.a 6 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | # Copyright 2011 Google Inc. All Rights Reserved. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | ######## Configuration Flags 16 | 17 | MAKE_JOBS := $(shell sh util/makejobs.sh) 18 | FLAGS_MAKE = $(MAKE_JOBS) -f ../util/Makefile 19 | FLAGS_11 = CC=gcc CXX=g++ CXXFLAGS=-std=c++11 20 | FLAGS_DBG = BFLAGS=-g3 21 | FLAGS_OPT = BFLAGS=-O3 22 | 23 | ######## Primary Rules 24 | 25 | default : debug 26 | 27 | build : build_opt11 28 | 29 | debug : test_dbg11 30 | 31 | test : test_dbg11 test_opt11 32 | 33 | install : test_opt11 34 | cd opt11 ; make $(FLAGS_MAKE) install 35 | 36 | ######## Build Directories 37 | 38 | dbg11 : 39 | mkdir dbg11 40 | 41 | opt11 : 42 | mkdir opt11 43 | 44 | clean : 45 | rm -rf dbg11 opt11 46 | 47 | 48 | ######## C++11 49 | 50 | build_dbg11 : dbg11 51 | cd dbg11 ; make $(FLAGS_MAKE) build $(FLAGS_DBG) $(FLAGS_11) 52 | build_opt11 : opt11 53 | cd opt11 ; make $(FLAGS_MAKE) build $(FLAGS_OPT) $(FLAGS_11) 54 | 55 | test_dbg11 : dbg11 56 | cd dbg11 ; make $(FLAGS_MAKE) test $(FLAGS_DBG) $(FLAGS_11) 57 | test_opt11 : opt11 58 | cd opt11 ; make $(FLAGS_MAKE) test $(FLAGS_OPT) $(FLAGS_11) 59 | 60 | -------------------------------------------------------------------------------- /README: -------------------------------------------------------------------------------- 1 | The Google Concurrency Library (GCL) is an attempt to export several 2 | internal C++ Google concurrency libraries in a form that the C++ 3 | standard committee may accept for TR2. 4 | 5 | 6 | cd to the directory into which you've checked out the Google 7 | Concurrency Library, and run: 8 | 9 | $ make 10 | $ make test 11 | 12 | 13 | `make clean` will take you back to a pristine checkout. 14 | -------------------------------------------------------------------------------- /archive/include/condition_variable.h: -------------------------------------------------------------------------------- 1 | // Copyright 2010 Google Inc. All Rights Reserved. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #ifndef STD_CONDITION_VARIABLE_ 16 | #define STD_CONDITION_VARIABLE_ 17 | 18 | #include 19 | #include 20 | #include 21 | #include 22 | 23 | #include "system_error.h" 24 | #include "mutex.h" 25 | 26 | struct ConditionMonitor; 27 | class condition_variable { 28 | public: 29 | condition_variable(); 30 | ~condition_variable(); 31 | 32 | void notify_one(); 33 | void notify_all(); 34 | 35 | void wait(unique_lock& lock); 36 | 37 | template 38 | void wait(unique_lock& lock, Predicate pred) { 39 | while (!pred()) { 40 | wait(lock); 41 | } 42 | } 43 | 44 | private: 45 | // Contains either the normal native handle or the test handle. See 46 | // condition_variable.cc and test_mutex.cc. 47 | union handle { 48 | pthread_cond_t native_handle; 49 | ConditionMonitor* monitor; 50 | }; 51 | handle handle_; 52 | 53 | typedef pthread_cond_t* native_handle_type; 54 | native_handle_type native_handle() { 55 | return &(handle_.native_handle); 56 | } 57 | 58 | ConditionMonitor* monitor() { 59 | return handle_.monitor; 60 | } 61 | 62 | // Deleted. 63 | condition_variable(const condition_variable&); 64 | condition_variable& operator=(const condition_variable&); 65 | }; 66 | 67 | #endif // STD_CONDITION_VARIABLE_ 68 | -------------------------------------------------------------------------------- /archive/include/functional.h: -------------------------------------------------------------------------------- 1 | #ifndef FUNCTIONAL_H 2 | #define FUNCTIONAL_H 3 | 4 | #if defined(__GXX_EXPERIMENTAL_CXX0X__) 5 | 6 | #include 7 | 8 | #else 9 | 10 | #include 11 | namespace std { 12 | using tr1::function; 13 | using tr1::bind; 14 | using tr1::ref; 15 | namespace placeholders = tr1::placeholders; 16 | using tr1::hash; 17 | } 18 | 19 | #endif 20 | 21 | #endif 22 | -------------------------------------------------------------------------------- /archive/include/test_mutex.h: -------------------------------------------------------------------------------- 1 | // Copyright 2010 Google Inc. All Rights Reserved. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #ifndef STD_TEST_MUTEX_ 16 | #define STD_TEST_MUTEX_ 17 | 18 | #include 19 | #include 20 | 21 | #include "functional.h" 22 | 23 | #include "mutex.h" 24 | #include "condition_variable.h" 25 | #include "thread.h" 26 | 27 | // Prints debug messages. The output is locked to ensure that only 28 | // one thread can print at a time. Prints out the thread id at the 29 | // start of the line. Sample usage: 30 | // 31 | // THREAD_DBG << "Unlocking " << this << ENDL 32 | // 33 | // Note that the two macros must be used in a pair to ensure that the 34 | // output is unlocked. 35 | // 36 | // TODO(alasdair): This is messy, and we need a proper thread-safe 37 | // logging facility. Keeping this for now as it's useful, but we 38 | // should clean this up. 39 | // 40 | #ifdef DEBUG 41 | #define THREAD_DBG MutexInternal::lock_stderr(); std::cerr 42 | #define ENDL std::endl; MutexInternal::unlock_stderr(); 43 | #else 44 | #define THREAD_DBG while (0) { std::cerr 45 | #define ENDL std::endl; } 46 | #endif 47 | 48 | namespace MutexInternal { 49 | class CompoundConditionVariable; 50 | extern void lock_stderr(); 51 | extern void unlock_stderr(); 52 | } 53 | 54 | class ThreadLatch; 55 | 56 | // Allows a test to wait until one of its threads reaches a blocked 57 | // state. When writing tests in which several threads contend for a 58 | // lock, this can be used to ensure that the test threads are in a 59 | // known state. 60 | // 61 | // Sample code: 62 | // 63 | // Class under test: 64 | // 65 | // class WorkQueue { 66 | // public: 67 | // // Blocks waiting until a task is available 68 | // Task get_task(); 69 | // 70 | // void add_task(const Task& task); 71 | // }; 72 | // 73 | // Test code 74 | // 75 | // void ProcessTask(WorkQueue *queue) { 76 | // Task task = queue->get_task(); 77 | // task.process(); 78 | // } 79 | // 80 | // TEST_F(WorkQueueTest, GetTask) { 81 | // TestTask task; 82 | // WorkQueue queue; 83 | // thread thread(std::bind(ProcessTask, &queue)); 84 | // 85 | // // Wait until the thread has blocked. We expect it to be in the 86 | // // ProcessTask method, waiting for get_task() to return. 87 | // ThreadMonitor::GetInstance()->WaitUntilBlocked(thread.get_id()); 88 | // EXPECT_FALSE(task.is_processed()); 89 | // 90 | // // Add the task. This should ublock the thread. 91 | // queue.add_task(task); 92 | // thread.join(); 93 | // EXPECT_TRUE(task.is_processed()); 94 | // } 95 | // 96 | 97 | class ThreadMonitor { 98 | public: 99 | // Obtains an instance of ThreadMonitor. This should not be deleted. 100 | static ThreadMonitor* GetInstance(); 101 | 102 | // Blocks the caller until the thread identified by "id" is blocked waiting 103 | // on a mutex or condition variable 104 | void WaitUntilBlocked(thread::id id); 105 | 106 | // Returns true if the given thread is blocked. 107 | bool IsBlocked(thread::id id); 108 | 109 | protected: 110 | friend class MutexInternal::_posix_mutex; 111 | friend class ::condition_variable; 112 | void OnThreadBlocked(thread::id id); 113 | void OnThreadReleased(thread::id id); 114 | 115 | private: 116 | ThreadMonitor(); 117 | ~ThreadMonitor(); 118 | ThreadLatch* GetThreadLatch(thread::id id); 119 | 120 | MutexInternal::CompoundConditionVariable* map_lock_; 121 | typedef std::map ThreadMap; 122 | 123 | ThreadMap blocked_waiters_; 124 | 125 | static ThreadMonitor gMonitor; 126 | }; 127 | 128 | #endif 129 | -------------------------------------------------------------------------------- /archive/include/thread.h: -------------------------------------------------------------------------------- 1 | // Copyright 2010 Google Inc. All Rights Reserved. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #ifndef STD_THREAD_ 16 | #define STD_THREAD_ 17 | 18 | #include 19 | #include 20 | #include 21 | 22 | #include "functional.h" 23 | 24 | // This is a really simple subset of C++11's std::thread (defined in 25 | // 30.3.1), that we'll use just for testing until we import or write a 26 | // more complete version. 27 | class thread { 28 | public: 29 | template explicit thread(F f); 30 | ~thread(); 31 | 32 | void join(); 33 | void detach(); 34 | // Represents the unique ID of a thread. 35 | class id; 36 | thread::id get_id() const; 37 | private: 38 | // Deleted 39 | thread(const thread&); 40 | void operator=(const thread&); 41 | 42 | void start(std::function start_func); 43 | 44 | pthread_t native_handle_; 45 | bool joinable_; 46 | }; 47 | 48 | template 49 | thread::thread(F f) { 50 | start(f); 51 | } 52 | 53 | namespace chrono { 54 | struct milliseconds { 55 | long long num; 56 | explicit milliseconds(long long num) : num(num) {} 57 | }; 58 | } 59 | 60 | namespace this_thread { 61 | void sleep_for(const chrono::milliseconds& delay); 62 | thread::id get_id(); 63 | } 64 | 65 | class thread::id { 66 | public: 67 | // Constructs an invalid ID. No valid executing thread will have this ID. 68 | id(); 69 | 70 | // Default copy constructor and assignment operators 71 | private: 72 | friend bool operator==(id, id); 73 | friend bool operator<(id, id); 74 | template 75 | friend std::basic_ostream& operator<<( 76 | std::basic_ostream& stream, id id); 77 | friend thread::id this_thread::get_id(); 78 | friend class thread; 79 | id(pthread_t id); 80 | unsigned long long_value() const; 81 | pthread_t id_; 82 | bool is_null_; 83 | }; 84 | 85 | bool operator==(thread::id x, thread::id y); 86 | bool operator!=(thread::id x, thread::id y); 87 | bool operator<(thread::id x, thread::id y); 88 | bool operator<=(thread::id x, thread::id y); 89 | bool operator>(thread::id x, thread::id y); 90 | bool operator>=(thread::id x, thread::id y); 91 | 92 | template 93 | std::basic_ostream& operator<<( 94 | std::basic_ostream& stream, thread::id id) { 95 | if (id.is_null_) { 96 | stream << "null thread"; 97 | } else { 98 | // TODO(alasdair): we only use this for EXPECT_EQ macros in testing, 99 | // but we should have a better implementation. 100 | if (sizeof(id.id_) == sizeof(unsigned long)) { 101 | unsigned long tid; 102 | memcpy(&tid, &id.id_, sizeof(unsigned long)); 103 | stream << std::hex << tid << std::dec; 104 | } else { 105 | stream << "???"; 106 | } 107 | } 108 | return stream; 109 | } 110 | 111 | #endif // STD_THREAD_ 112 | -------------------------------------------------------------------------------- /archive/include/unordered_map.h: -------------------------------------------------------------------------------- 1 | #ifndef CXX11_UNORDERED_MAP_H 2 | #define CXX11_UNORDERED_MAP_H 3 | 4 | #if defined(__GNUC__) && defined(__GXX_EXPERIMENTAL_CXX0X__) && __GNUC__ == 4 5 | 6 | #include 7 | 8 | #else 9 | 10 | #include 11 | namespace std { 12 | using tr1::unordered_map; 13 | } 14 | 15 | #endif 16 | 17 | #endif 18 | -------------------------------------------------------------------------------- /archive/include/unordered_set.h: -------------------------------------------------------------------------------- 1 | #ifndef CXX11_UNORDERED_SET_H 2 | #define CXX11_UNORDERED_SET_H 3 | 4 | #if defined(__GNUC__) && defined(__GXX_EXPERIMENTAL_CXX0X__) && __GNUC__ == 4 5 | 6 | #include 7 | 8 | #else 9 | 10 | #include 11 | namespace std { 12 | using tr1::unordered_set; 13 | } 14 | 15 | #endif 16 | 17 | #endif 18 | -------------------------------------------------------------------------------- /archive/src/atomic.c: -------------------------------------------------------------------------------- 1 | // Copyright 2010 Google Inc. All Rights Reserved. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #include 16 | #include "atomic.h" 17 | 18 | 19 | #if defined(__GNUC__) 20 | #if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ > 0) 21 | #define USE_SYNC 22 | #endif 23 | #endif 24 | 25 | void atomic_thread_fence( memory_order __x__ ) 26 | { 27 | #ifdef USE_SYNC 28 | __sync_synchronize(); 29 | #endif 30 | } 31 | 32 | void atomic_signal_fence( memory_order __x__ ) 33 | { 34 | __asm__ __volatile__ ("" ::: "memory"); 35 | } 36 | 37 | bool __atomic_flag_test_and_set_explicit 38 | ( volatile atomic_flag* __a__, memory_order __x__ ) 39 | { 40 | #ifdef USE_SYNC 41 | if ( __x__ >= memory_order_acq_rel ) 42 | __sync_synchronize(); 43 | return __sync_lock_test_and_set( &(__a__->__f__), 1 ); 44 | #else 45 | bool result = __a__->__f__; 46 | __a__->__f__ = true; 47 | return result; 48 | #endif 49 | } 50 | 51 | void __atomic_flag_clear_explicit 52 | ( volatile atomic_flag* __a__, memory_order __x__ ) 53 | { 54 | #ifdef USE_SYNC 55 | __sync_lock_release( &(__a__->__f__) ); 56 | if ( __x__ >= memory_order_acq_rel ) 57 | __sync_synchronize(); 58 | #else 59 | __a__->__f__ = false; 60 | #endif 61 | } 62 | 63 | void __atomic_flag_wait_explicit__( volatile atomic_flag* __a__, 64 | memory_order __x__ ) 65 | { while ( __atomic_flag_test_and_set_explicit( __a__, __x__ ) ); } 66 | 67 | #define LOGSIZE 4 68 | 69 | static atomic_flag volatile __atomic_flag_anon_table__[ 1 << LOGSIZE ] = 70 | { 71 | ATOMIC_FLAG_INIT, ATOMIC_FLAG_INIT, ATOMIC_FLAG_INIT, ATOMIC_FLAG_INIT, 72 | ATOMIC_FLAG_INIT, ATOMIC_FLAG_INIT, ATOMIC_FLAG_INIT, ATOMIC_FLAG_INIT, 73 | ATOMIC_FLAG_INIT, ATOMIC_FLAG_INIT, ATOMIC_FLAG_INIT, ATOMIC_FLAG_INIT, 74 | ATOMIC_FLAG_INIT, ATOMIC_FLAG_INIT, ATOMIC_FLAG_INIT, ATOMIC_FLAG_INIT, 75 | }; 76 | 77 | volatile atomic_flag* __atomic_flag_for_address__( const volatile void* __z__ ) 78 | { 79 | uintptr_t __u__ = (uintptr_t)__z__; 80 | __u__ += (__u__ >> 2) + (__u__ << 4); 81 | __u__ += (__u__ >> 7) + (__u__ << 5); 82 | __u__ += (__u__ >> 17) + (__u__ << 13); 83 | if ( sizeof(uintptr_t) > 4 ) __u__ += (__u__ >> 31); 84 | __u__ &= ~((~(uintptr_t)0) << LOGSIZE); 85 | return __atomic_flag_anon_table__ + __u__; 86 | } 87 | 88 | -------------------------------------------------------------------------------- /archive/src/condition_variable.cc: -------------------------------------------------------------------------------- 1 | // Copyright 2009 Google Inc. All Rights Reserved. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #include "condition_variable.h" 16 | 17 | condition_variable::condition_variable() { 18 | handle_err_return(pthread_cond_init(native_handle(), NULL)); 19 | } 20 | 21 | condition_variable::~condition_variable() { 22 | handle_err_return(pthread_cond_destroy(native_handle())); 23 | } 24 | 25 | void condition_variable::notify_one() { 26 | handle_err_return(pthread_cond_signal(native_handle())); 27 | } 28 | 29 | void condition_variable::notify_all() { 30 | handle_err_return(pthread_cond_broadcast(native_handle())); 31 | } 32 | 33 | void condition_variable::wait(unique_lock& lock) { 34 | int result = pthread_cond_wait(native_handle(), 35 | lock.mutex()->native_handle()); 36 | if (result == EINTR) 37 | result = 0; 38 | handle_err_return(result); 39 | } 40 | -------------------------------------------------------------------------------- /archive/src/mutex.cc: -------------------------------------------------------------------------------- 1 | // Copyright 2009 Google Inc. All Rights Reserved. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #include 16 | 17 | #include "mutex.h" 18 | 19 | const defer_lock_t defer_lock = {}; 20 | const try_to_lock_t try_to_lock = {}; 21 | const adopt_lock_t adopt_lock = {}; 22 | 23 | namespace MutexInternal { 24 | _posix_mutex::_posix_mutex(int mutex_type) { 25 | pthread_mutexattr_t mutex_attribute; 26 | handle_err_return(pthread_mutexattr_init(&mutex_attribute)); 27 | handle_err_return(pthread_mutexattr_settype(&mutex_attribute, 28 | mutex_type)); 29 | handle_err_return(pthread_mutex_init(native_handle(), &mutex_attribute)); 30 | handle_err_return(pthread_mutexattr_destroy(&mutex_attribute)); 31 | } 32 | 33 | _posix_mutex::~_posix_mutex() { 34 | handle_err_return(pthread_mutex_destroy(native_handle())); 35 | } 36 | 37 | void _posix_mutex::lock() { 38 | handle_err_return(pthread_mutex_lock(native_handle())); 39 | } 40 | 41 | bool _posix_mutex::try_lock() { 42 | int result = pthread_mutex_trylock(native_handle()); 43 | if (result == 0) { 44 | return true; 45 | } else if (result != EBUSY) { 46 | handle_err_return(result); 47 | } 48 | return false; 49 | } 50 | 51 | void _posix_mutex::unlock() { 52 | handle_err_return(pthread_mutex_unlock(native_handle())); 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /archive/src/thread.cc: -------------------------------------------------------------------------------- 1 | // Copyright 2010 Google Inc. All Rights Reserved. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | 22 | #include "thread.h" 23 | #include "system_error.h" 24 | 25 | namespace { 26 | 27 | struct thread_bootstrap_arg { 28 | std::function start_func; 29 | }; 30 | 31 | static void* thread_bootstrap(void* void_arg) { 32 | const std::auto_ptr arg( 33 | static_cast(void_arg)); 34 | // Run the thread. TODO: This should actually catch and propagate 35 | // exceptions. 36 | arg->start_func(); 37 | // C++ threads don't return anything. 38 | return NULL; 39 | } 40 | 41 | } 42 | 43 | thread::~thread() { 44 | if (joinable_) { 45 | std::terminate(); 46 | } 47 | } 48 | 49 | void thread::start(std::function f) { 50 | pthread_attr_t attr; 51 | pthread_attr_init(&attr); 52 | thread_bootstrap_arg* arg = new (std::nothrow) thread_bootstrap_arg; 53 | if (arg == NULL) { 54 | pthread_attr_destroy(&attr); 55 | throw std::bad_alloc(); 56 | } 57 | arg->start_func = f; 58 | joinable_ = true; 59 | int result = pthread_create(&native_handle_, &attr, thread_bootstrap, arg); 60 | if (result != 0) { 61 | delete arg; 62 | pthread_attr_destroy(&attr); 63 | handle_err_return(result); 64 | } 65 | pthread_attr_destroy(&attr); 66 | } 67 | 68 | void thread::join() { 69 | if (joinable_ == false) { 70 | throw std::system_error(std::make_error_code(std::errc::invalid_argument)); 71 | } 72 | joinable_ = false; 73 | handle_err_return(pthread_join(native_handle_, NULL)); 74 | } 75 | 76 | void thread::detach() { 77 | if (joinable_ == false) { 78 | throw std::system_error(std::make_error_code(std::errc::invalid_argument)); 79 | } 80 | joinable_ = false; 81 | handle_err_return(pthread_detach(native_handle_)); 82 | } 83 | 84 | void this_thread::sleep_for(const chrono::milliseconds& delay) { 85 | timespec tm; 86 | tm.tv_sec = delay.num / 1000; 87 | tm.tv_nsec = (delay.num % 1000) * 1000 * 1000; 88 | errno = 0; 89 | do { 90 | nanosleep(&tm, &tm); 91 | } while (errno == EINTR); 92 | } 93 | 94 | thread::id thread::get_id() const { 95 | if (joinable_) { 96 | return thread::id(native_handle_); 97 | } else { 98 | return thread::id(); 99 | } 100 | } 101 | 102 | thread::id::id() : is_null_(true) { 103 | } 104 | 105 | thread::id::id(pthread_t id) : id_(id), is_null_(false) { 106 | } 107 | 108 | thread::id this_thread::get_id() { 109 | return thread::id(pthread_self()); 110 | } 111 | 112 | bool operator==(thread::id x, thread::id y) { 113 | return (x.is_null_ && y.is_null_) || 114 | (!x.is_null_ && !y.is_null_ && pthread_equal(x.id_, y.id_)); 115 | } 116 | 117 | bool operator!=(thread::id x, thread::id y) { 118 | return !(x == y); 119 | } 120 | 121 | // TODO(alasdair): Used for comparison operator. Need better 122 | // implementation of this, or alternative way to implement these 123 | // methods. 124 | unsigned long thread::id::long_value() const { 125 | assert(!is_null_ && sizeof(id_) == sizeof(unsigned long)); 126 | unsigned long tid; 127 | memcpy(&tid, &id_, sizeof(unsigned long)); 128 | return tid; 129 | } 130 | 131 | // Comparison. To satisfy an equivalence relationship induced by a 132 | // strict weak ordering, we define a and b to be equivalent if 133 | // !(a < b) && !(b < a). See 25.5.7. To ensure that two null ids 134 | // are equivalent, we ensure that nothing is ever less than null. 135 | bool operator<(thread::id x, thread::id y) { 136 | if (y.is_null_) { 137 | return false; 138 | } else if (x.is_null_) { 139 | return true; 140 | } else { 141 | return x.long_value() < y.long_value(); 142 | } 143 | } 144 | 145 | bool operator<=(thread::id x, thread::id y) { 146 | return ! (y < x); 147 | } 148 | 149 | bool operator>(thread::id x, thread::id y) { 150 | return ! (x <= y); 151 | } 152 | 153 | bool operator>=(thread::id x, thread::id y) { 154 | return ! (x < y); 155 | } 156 | -------------------------------------------------------------------------------- /archive/testing/condition_variable_test.cc: -------------------------------------------------------------------------------- 1 | // Copyright 2009 Google Inc. All Rights Reserved. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | // Tests thread behaviour using the test condition variable. Verifies 16 | // that the test framework allows us to block until a thread is 17 | // waiting on a condition variable. 18 | 19 | #include "functional.h" 20 | 21 | #include "thread.h" 22 | 23 | #include "test_mutex.h" 24 | 25 | #include "gmock/gmock.h" 26 | 27 | static const int kNumThreads = 1; 28 | 29 | static void WaitOnConditionVariable(mutex& mu, 30 | condition_variable& cv, 31 | bool* ready) { 32 | unique_lock lock(mu); 33 | cv.wait(lock); 34 | *ready = true; 35 | } 36 | 37 | // Verifies that WaitUntilBlocked will wait until a thread is waiitng 38 | // on a condition_variable 39 | TEST(ConditionVariableTest, WaitUntilBlocked) { 40 | bool ready = false; 41 | mutex mu; 42 | condition_variable cv; 43 | thread thr(std::bind( 44 | WaitOnConditionVariable, std::ref(mu), std::ref(cv), &ready)); 45 | ThreadMonitor::GetInstance()->WaitUntilBlocked(thr.get_id()); 46 | EXPECT_FALSE(ready); 47 | mu.lock(); 48 | cv.notify_one(); 49 | mu.unlock(); 50 | thr.join(); 51 | EXPECT_TRUE(ready); 52 | } 53 | 54 | // Verifies that WaitUntilBlocked will wait until a thread is waiting 55 | // on a condition_variable 56 | TEST(ConditionVariableTest, WaitUntilBlockedMultiThreaded) { 57 | mutex mu; 58 | condition_variable cv; 59 | thread* threads[kNumThreads]; 60 | bool ready[kNumThreads]; 61 | for (int i = 0; i < kNumThreads; i++) { 62 | ready[i] = false; 63 | threads[i] = new thread(std::bind(WaitOnConditionVariable, 64 | std::ref(mu), 65 | std::ref(cv), 66 | ready+ i)); 67 | } 68 | ThreadMonitor* monitor = ThreadMonitor::GetInstance(); 69 | for (int i = 0; i < kNumThreads; i++) { 70 | monitor->WaitUntilBlocked(threads[i]->get_id()); 71 | EXPECT_FALSE(ready[i]); 72 | } 73 | mu.lock(); 74 | cv.notify_all(); 75 | mu.unlock(); 76 | for (int i = 0; i < kNumThreads; i++) { 77 | threads[i]->join(); 78 | delete threads[i]; 79 | EXPECT_TRUE(ready[i]); 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /archive/testing/test_mutex_test.cc: -------------------------------------------------------------------------------- 1 | // Copyright 2010 Google Inc. All Rights Reserved. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | // Tests thread behaviour using the test mutex classes. Verifies that 16 | // the test framework allows us to block until a thread reaches a 17 | // particular state. 18 | 19 | #include "functional.h" 20 | 21 | #include "mutex.h" 22 | #include "thread.h" 23 | 24 | #include "test_mutex.h" 25 | 26 | #include "gmock/gmock.h" 27 | 28 | static const int kNumThreads = 100; 29 | 30 | // Sets 'id' to the id of this thread. 31 | void SetThreadId(thread::id* id) { 32 | *id = this_thread::get_id(); 33 | } 34 | 35 | static void LockMutex(mutex& mu, bool* ready) { 36 | mu.lock(); 37 | *ready = true; 38 | mu.unlock(); 39 | } 40 | 41 | // Verifies that wait_until_blocked will wait until a thread reaches 42 | TEST(ThreadTest, WaitUntilBlocked) { 43 | mutex mu; 44 | mu.lock(); 45 | bool ready = false; 46 | thread thr(std::bind(LockMutex, std::ref(mu), &ready)); 47 | ThreadMonitor::GetInstance()->WaitUntilBlocked(thr.get_id()); 48 | EXPECT_FALSE(ready); 49 | mu.unlock(); 50 | thr.join(); 51 | EXPECT_TRUE(ready); 52 | } 53 | 54 | TEST(ThreadTest, ManyThreads) { 55 | mutex mu; 56 | mu.lock(); 57 | thread* threads[kNumThreads]; 58 | bool ready[kNumThreads]; 59 | for (int i = 0; i < kNumThreads; i++) { 60 | ready[i] = false; 61 | threads[i] = new thread(std::bind(LockMutex, std::ref(mu), ready + i)); 62 | } 63 | mu.unlock(); 64 | for (int i = 0; i < kNumThreads; i++) { 65 | threads[i]->join(); 66 | EXPECT_TRUE(ready[i]); 67 | delete threads[i]; 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /archive/testing/thread_test.cc: -------------------------------------------------------------------------------- 1 | // Copyright 2009 Google Inc. All Rights Reserved. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | // This file is a rudimentary test of the thread class. It primarily 16 | // serves to make sure the build system works. 17 | 18 | #include "functional.h" 19 | 20 | #include "mutex.h" 21 | #include "thread.h" 22 | 23 | #include "gmock/gmock.h" 24 | 25 | void WaitForThenSet(mutex& mu, bool* ready, bool* signal) { 26 | lock_guard l(mu); 27 | while (!*ready) { 28 | mu.unlock(); 29 | this_thread::sleep_for(chrono::milliseconds(10)); 30 | mu.lock(); 31 | } 32 | *signal = true; 33 | } 34 | 35 | // Sets 'id' to the id of this thread. 36 | void SetThreadId(thread::id* id) { 37 | *id = this_thread::get_id(); 38 | } 39 | 40 | TEST(ThreadTest, StartsNewThread) { 41 | bool ready = false; 42 | bool signal = false; 43 | mutex mu; 44 | thread thr(std::bind(WaitForThenSet, std::ref(mu), &ready, &signal)); 45 | lock_guard l(mu); 46 | EXPECT_FALSE(signal); 47 | ready = true; 48 | while (!signal) { 49 | mu.unlock(); 50 | this_thread::sleep_for(chrono::milliseconds(10)); 51 | mu.lock(); 52 | } 53 | thr.detach(); 54 | } 55 | 56 | TEST(ThreadTest, JoinSynchronizes) { 57 | bool ready = true; 58 | bool signal = false; 59 | mutex mu; 60 | thread thr(std::bind(WaitForThenSet, std::ref(mu), &ready, &signal)); 61 | thr.join(); 62 | EXPECT_TRUE(signal); 63 | } 64 | 65 | TEST(ThreadTest, GetId) { 66 | thread::id id_set_by_thread; 67 | thread::id this_thread_id = this_thread::get_id(); 68 | thread thr(std::bind(SetThreadId, &id_set_by_thread)); 69 | thread::id id_of_thread = thr.get_id(); 70 | thr.join(); 71 | // The id that was set in SetThreadId() should equal the id of the 72 | // thread we created, and should not equal the current thread id. 73 | EXPECT_TRUE(id_set_by_thread == id_of_thread); 74 | EXPECT_FALSE(id_set_by_thread == this_thread_id); 75 | 76 | thread::id greater, lesser; 77 | if (this_thread_id < id_of_thread) { 78 | lesser = this_thread_id; 79 | greater = id_of_thread; 80 | } else { 81 | lesser = id_of_thread; 82 | greater = this_thread_id; 83 | } 84 | EXPECT_TRUE(greater > lesser); 85 | EXPECT_TRUE(lesser < greater); 86 | 87 | EXPECT_TRUE(greater >= lesser); 88 | EXPECT_FALSE(lesser >= greater); 89 | 90 | EXPECT_TRUE(lesser <= greater); 91 | EXPECT_FALSE(greater <= lesser); 92 | 93 | EXPECT_TRUE(lesser >= lesser); 94 | EXPECT_TRUE(lesser <= lesser); 95 | 96 | // The null/empty thread id should not equal the id of any real 97 | // thread. 98 | thread::id null_id; 99 | EXPECT_NE(id_set_by_thread, null_id); 100 | EXPECT_NE(this_thread_id, null_id); 101 | 102 | // After a join, a thread should no longer have an id. 103 | EXPECT_TRUE(null_id == thr.get_id()); 104 | 105 | // Verify behaviour of null id in comparisons 106 | EXPECT_TRUE(null_id == null_id); 107 | EXPECT_FALSE(null_id == id_set_by_thread); 108 | 109 | EXPECT_TRUE(null_id < this_thread_id); 110 | EXPECT_FALSE(this_thread_id < null_id); 111 | 112 | EXPECT_TRUE(this_thread_id > null_id); 113 | EXPECT_FALSE(null_id > this_thread_id); 114 | 115 | EXPECT_TRUE(null_id <= this_thread_id); 116 | EXPECT_FALSE(this_thread_id <= null_id); 117 | 118 | EXPECT_TRUE(this_thread_id >= null_id); 119 | EXPECT_FALSE(null_id >= this_thread_id); 120 | 121 | EXPECT_FALSE(null_id < null_id); 122 | EXPECT_TRUE(null_id <= null_id); 123 | } 124 | -------------------------------------------------------------------------------- /include/barrier.h: -------------------------------------------------------------------------------- 1 | // Copyright 2011 Google Inc. All Rights Reserved. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #ifndef GCL_BARRIER_ 16 | #define GCL_BARRIER_ 17 | 18 | #include 19 | #include 20 | 21 | #include 22 | #include 23 | #include 24 | #include 25 | 26 | namespace gcl { 27 | 28 | // Allows a set of threads to wait until all threads have reached a 29 | // common point. 30 | class barrier { 31 | public: 32 | explicit barrier(std::ptrdiff_t num_threads); 33 | 34 | ~barrier(); 35 | 36 | barrier(const barrier&) = delete; 37 | barrier& operator=(const barrier&) = delete; 38 | 39 | void arrive_and_wait(); 40 | 41 | void arrive_and_drop(); 42 | 43 | private: 44 | void check_all_threads_exited(); 45 | bool all_threads_exited(); 46 | bool all_threads_waiting(); 47 | 48 | 49 | std::mutex mutex_; 50 | std::condition_variable idle_; 51 | std::condition_variable ready_; 52 | std::ptrdiff_t thread_count_; 53 | std::ptrdiff_t num_waiting_; 54 | std::atomic num_to_leave_; 55 | }; 56 | } 57 | #endif // GCL_BARRIER_ 58 | -------------------------------------------------------------------------------- /include/closed_error.h: -------------------------------------------------------------------------------- 1 | // Copyright 2010 Google Inc. All Rights Reserved. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #ifndef GCL_CLOSED_ERROR_ 16 | #define GCL_CLOSED_ERROR_ 17 | 18 | #include 19 | #include 20 | #include 21 | 22 | namespace gcl { 23 | 24 | // Thrown when attemmpting to read from a closed source, or write to a 25 | // closed sink. 26 | class closed_error : public std::logic_error { 27 | public: 28 | explicit closed_error(const std::string& description) 29 | : std::logic_error(description) { 30 | } 31 | }; 32 | 33 | } // end namespace 34 | #endif // GCL_CLOSED_ERROR_ 35 | -------------------------------------------------------------------------------- /include/countdown_latch.h: -------------------------------------------------------------------------------- 1 | // Copyright 2009 Google Inc. All Rights Reserved. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #ifndef GCL_COUNTDOWN_LATCH_ 16 | #define GCL_COUNTDOWN_LATCH_ 17 | #include 18 | #include 19 | 20 | namespace gcl { 21 | 22 | // A countdown_latch allows one or more threads to block until an 23 | // operation is completed. A countdown_latch is initialized with a 24 | // count value. Calls to count_down() will decrement this count. Calls 25 | // to wait() will block until the count reaches zero. All calls to 26 | // count_down() happen before any call to wait() returns. 27 | class countdown_latch { 28 | public: 29 | 30 | // Creates a new countdown_latch with the given count. 31 | explicit countdown_latch(unsigned int count); 32 | 33 | // Destroys the countdown_latch. If the latch is destroyed while 34 | // other threads are blocked in wait(), or are invoking count_down(), 35 | // the behaviour is undefined. Note that a single waiter can safely 36 | // destroy the latch as soon as it returns from wait(). 37 | ~countdown_latch(); 38 | 39 | // Waits until the count is decremented to 0. If the count is 40 | // already 0, this is a no-op. 41 | void wait(); 42 | 43 | // Decrements the count. If the count reaches 0, any threads blocked 44 | // in wait() will be released. If the count is already 0, 45 | // throws std::system_error. 46 | void count_down(); 47 | 48 | private: 49 | // The counter for this latch. 50 | unsigned int count_; 51 | 52 | // The condition that blocks until the count reaches 0 53 | std::condition_variable condition_; 54 | std::mutex condition_mutex_; 55 | 56 | // Disallow copy and assign 57 | countdown_latch(const countdown_latch&); 58 | countdown_latch& operator=(const countdown_latch&); 59 | }; 60 | 61 | } // End namespace gcl 62 | 63 | #endif // GCL_COUNTDOWN_LATCH_ 64 | -------------------------------------------------------------------------------- /include/debug.h: -------------------------------------------------------------------------------- 1 | // Copyright 2011 Google Inc. All Rights Reserved. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #ifndef GCL_DEBUG_ 16 | #define GCL_DEBUG_ 17 | 18 | #include 19 | 20 | #include 21 | 22 | #include "stream_mutex.h" 23 | 24 | namespace gcl { 25 | 26 | extern stream_mutex dbg_stream; 27 | 28 | // Prints debug messages to stderr. The output is locked to ensure that only one 29 | // thread can print at a time. Prints out the thread id at the start of the 30 | // line. Sample usage: 31 | // 32 | // DBG << "Unlocking " << this << std::eol; 33 | // 34 | #define DBG dbg_stream << this_thread::get_id() << " : " 35 | 36 | } // namespace gcl 37 | #endif 38 | -------------------------------------------------------------------------------- /include/dynarray.h: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | namespace std { 6 | 7 | struct bad_array_length { }; 8 | 9 | template< class T > 10 | struct dynarray 11 | { 12 | // types: 13 | typedef T value_type; 14 | typedef T& reference; 15 | typedef const T& const_reference; 16 | typedef T* iterator; 17 | typedef const T* const_iterator; 18 | typedef std::reverse_iterator reverse_iterator; 19 | typedef std::reverse_iterator const_reverse_iterator; 20 | typedef size_t size_type; 21 | typedef ptrdiff_t difference_type; 22 | 23 | // fields: 24 | private: 25 | T* store; 26 | size_type count; 27 | 28 | // helper functions: 29 | void check(size_type n) 30 | { if ( n >= count ) throw out_of_range("dynarray"); } 31 | T* alloc(size_type n) 32 | { if ( n > std::numeric_limits::max()/sizeof(T) ) 33 | throw std::bad_array_length(); 34 | return reinterpret_cast( new char[ n*sizeof(T) ] ); } 35 | 36 | public: 37 | // construct and destruct: 38 | dynarray() = delete; 39 | const dynarray operator=(const dynarray&) = delete; 40 | 41 | explicit dynarray(size_type c) 42 | : store( alloc( c ) ), count( c ) 43 | { size_type i; 44 | try { 45 | for ( size_type i = 0; i < count; ++i ) 46 | new (store+i) T; 47 | } catch ( ... ) { 48 | for ( ; i > 0; --i ) 49 | (store+(i-1))->~T(); 50 | throw; 51 | } } 52 | 53 | dynarray(const dynarray& d) 54 | : store( alloc( d.count ) ), count( d.count ) 55 | { try { uninitialized_copy( d.begin(), d.end(), begin() ); } 56 | catch ( ... ) { delete store; throw; } } 57 | 58 | ~dynarray() 59 | { for ( size_type i = 0; i < count; ++i ) 60 | (store+i)->~T(); 61 | delete[] store; } 62 | 63 | // iterators: 64 | iterator begin() { return store; } 65 | const_iterator begin() const { return store; } 66 | const_iterator cbegin() const { return store; } 67 | iterator end() { return store + count; } 68 | const_iterator end() const { return store + count; } 69 | const_iterator cend() const { return store + count; } 70 | 71 | reverse_iterator rbegin() 72 | { return reverse_iterator(end()); } 73 | const_reverse_iterator rbegin() const 74 | { return reverse_iterator(end()); } 75 | reverse_iterator rend() 76 | { return reverse_iterator(begin()); } 77 | const_reverse_iterator rend() const 78 | { return reverse_iterator(begin()); } 79 | 80 | // capacity: 81 | size_type size() const { return count; } 82 | size_type max_size() const { return count; } 83 | bool empty() const { return count == 0; } 84 | 85 | // element access: 86 | reference operator[](size_type n) { return store[n]; } 87 | const_reference operator[](size_type n) const { return store[n]; } 88 | 89 | reference front() { return store[0]; } 90 | const_reference front() const { return store[0]; } 91 | reference back() { return store[count-1]; } 92 | const_reference back() const { return store[count-1]; } 93 | 94 | const_reference at(size_type n) const { check(n); return store[n]; } 95 | reference at(size_type n) { check(n); return store[n]; } 96 | 97 | // data access: 98 | T* data() { return store; } 99 | const T* data() const { return store; } 100 | }; 101 | 102 | } // namespace std 103 | -------------------------------------------------------------------------------- /include/flex_barrier.h: -------------------------------------------------------------------------------- 1 | // Copyright 2011 Google Inc. All Rights Reserved. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #ifndef GCL_FLEX_BARRIER_ 16 | #define GCL_FLEX_BARRIER_ 17 | 18 | #include 19 | #include 20 | 21 | #include 22 | #include 23 | #include 24 | #include "scoped_guard.h" 25 | 26 | #include 27 | 28 | namespace gcl { 29 | 30 | // Allows a set of threads to wait until all threads have reached a 31 | // common point. 32 | class flex_barrier { 33 | public: 34 | template 35 | flex_barrier(std::ptrdiff_t num_threads, F completion) throw (std::invalid_argument); 36 | 37 | explicit flex_barrier(ptrdiff_t num_threads); 38 | 39 | ~flex_barrier(); 40 | 41 | flex_barrier(const flex_barrier&) = delete; 42 | flex_barrier& operator=(const flex_barrier&) = delete; 43 | 44 | void arrive_and_wait(); 45 | void arrive_and_drop(); 46 | 47 | private: 48 | std::ptrdiff_t completion_wrapper(std::function completion); 49 | void reset(std::ptrdiff_t num_threads); 50 | bool all_threads_exited(); 51 | bool all_threads_waiting(); 52 | void on_countdown(); 53 | 54 | std::ptrdiff_t thread_count_; 55 | std::ptrdiff_t new_thread_count_; 56 | 57 | std::mutex mutex_; 58 | std::condition_variable idle_; 59 | std::condition_variable ready_; 60 | std::ptrdiff_t num_waiting_; 61 | std::atomic num_to_leave_; 62 | 63 | std::function completion_fn_; 64 | }; 65 | 66 | template 67 | flex_barrier::flex_barrier(std::ptrdiff_t num_threads, 68 | F completion) throw(std::invalid_argument) 69 | : thread_count_(num_threads), num_waiting_(0), completion_fn_(completion) { 70 | if (num_threads == 0) { 71 | throw std::invalid_argument("num_threads is 0"); 72 | } 73 | num_to_leave_ = 0; //std::atomic_init(&num_to_leave_, 0); 74 | } 75 | 76 | } 77 | #endif // GCL_FLEX_BARRIER_ 78 | -------------------------------------------------------------------------------- /include/gcl_string.h: -------------------------------------------------------------------------------- 1 | // Copyright 2011 Google Inc. All Rights Reserved. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #include 16 | #include 17 | 18 | #ifndef GCL_STRING_ 19 | #define GCL_STRING_ 20 | 21 | // Implementation of some of the string utilities from C++11. 22 | template 23 | std::string to_string(const T& t) { 24 | std::stringstream ss; 25 | ss << t; 26 | return ss.str(); 27 | } 28 | 29 | #endif //GCL_STRING_ 30 | -------------------------------------------------------------------------------- /include/iterator_queue.h: -------------------------------------------------------------------------------- 1 | // Copyright 2011 Google Inc. All Rights Reserved. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #ifndef GCL_ITERATOR_QUEUE_ 16 | #define GCL_ITERATOR_QUEUE_ 17 | 18 | #include 19 | 20 | #include 21 | 22 | #include "closed_error.h" 23 | 24 | namespace gcl { 25 | 26 | // A partial queue implementation based on std:: iterators. This is 27 | // designed to be used in conjunction with a gcl::source, and allows a 28 | // source to be created from a collection. This is useful when 29 | // creating gcl::Pipelines that read from a collection. The queue will 30 | // be closed when the iterator reaches the end 31 | // 32 | // The iterator_queue is threadsafe in that it can be accessed from 33 | // multiple threads, but is not safe against modifications to the 34 | // underlying collection from which the iterators are derived. Once an 35 | // iterator_queue is created, the underlying collection should not 36 | // be modified. 37 | // 38 | // TODO(alasdair): Do we need this class? If so, should this be based 39 | // on concurrent collections? 40 | 41 | template 42 | class iterator_queue { 43 | public: 44 | // Creates a new queue. 45 | iterator_queue(const Iterator& start, const Iterator& end) 46 | : it_(start), end_(end) { 47 | } 48 | 49 | typename std::iterator_traits::value_type pop() { 50 | std::unique_lock l(lock_); 51 | if (it_ == end_) { 52 | throw closed_error("Iterator at end"); 53 | } 54 | typename std::iterator_traits::value_type result = *it_; 55 | ++it_; 56 | return result; 57 | } 58 | 59 | bool is_closed() { 60 | std::unique_lock l(lock_); 61 | return (it_ == end_); 62 | } 63 | 64 | private: 65 | Iterator it_; 66 | Iterator end_; 67 | std::mutex lock_; 68 | 69 | iterator_queue(const iterator_queue& other); 70 | iterator_queue& operator=(const iterator_queue& other); 71 | }; 72 | 73 | template 74 | iterator_queue make_queue(I& begin, I& end) { 75 | return iterator_queue(begin, end); 76 | } 77 | 78 | } // End namespace gcl 79 | #endif // GCL_ITERATOR_QUEUE_ 80 | -------------------------------------------------------------------------------- /include/latch.h: -------------------------------------------------------------------------------- 1 | // Copyright 2011 Google Inc. All Rights Reserved. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #ifndef GCL_LATCH_ 16 | #define GCL_LATCH_ 17 | 18 | #include 19 | #include 20 | #include 21 | 22 | namespace gcl { 23 | 24 | // A latch allows one or more threads to block until an operation is 25 | // completed. A latch is initialized with a count value. Calls to count_down() 26 | // will decrement this count. Calls to wait() will block until the count 27 | // reaches zero. All calls to count_down() happen before any call to wait() 28 | // returns. 29 | class latch { 30 | public: 31 | // Creates a new latch with the given count. 32 | explicit latch(std::ptrdiff_t count); 33 | 34 | ~latch(); 35 | 36 | latch(const latch&) = delete; 37 | latch& operator=(const latch&) = delete; 38 | 39 | void count_down_and_wait(); 40 | 41 | void count_down(std::ptrdiff_t n = 1); 42 | 43 | bool is_ready() const noexcept; 44 | 45 | void wait() const; 46 | 47 | private: 48 | // The counter for this latch. 49 | std::ptrdiff_t count_; 50 | 51 | // Counts the number of threads that are currently waiting 52 | mutable std::atomic waiting_; 53 | 54 | // The condition that blocks until the count reaches 0 55 | mutable std::condition_variable condition_; 56 | mutable std::mutex condition_mutex_; 57 | }; 58 | 59 | } // End namespace gcl 60 | 61 | #endif // GCL_LATCH_ 62 | -------------------------------------------------------------------------------- /include/mutable_thread.h: -------------------------------------------------------------------------------- 1 | // Copyright 2011 Google Inc. All Rights Reserved. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #ifndef GCL_MUTABLE_THREAD__ 16 | #define GCL_MUTABLE_THREAD__ 17 | 18 | #include 19 | 20 | #include 21 | #include 22 | #include 23 | #include 24 | 25 | namespace gcl { 26 | 27 | // Variation on the thread class which allows threads to be put to sleep when 28 | // not working on anything and awoken again with new work. The class allows 29 | // work to be queued up one-deep (a single extra item of execution). The thread 30 | // 31 | // This is a building block for more complex thread execution classes which 32 | // need to be able to stop and restart threads with new work as well as to 33 | // re-allocate threads to new work queues or tasks. 34 | // 35 | // TODO: Refine the execute behavior slightly to see if it should be extended 36 | // to allow the thread to enqueue arbitrary numbers of items or not. The 37 | // current behavior allows only a single task to enqueue which means behavior 38 | // is slightly inconsistent (execute will return even if the task is not 39 | // guaranteed to be able to execute). 40 | class mutable_thread { 41 | public: 42 | // Mutable thread works a little differently from a normal thread in that it 43 | // can start in an empty state. 44 | mutable_thread(); 45 | ~mutable_thread(); 46 | 47 | templateexplicit mutable_thread(F f); 48 | 49 | // Thread join. Will not complete joining until all queued work is completed 50 | // (makes no guarantees that the thread will terminate). 51 | void join(); 52 | 53 | // Setup function for execution if there isn't currently something executing 54 | // or if there is only a single task currently executing. 55 | // Return false if thread is currently doing other work. 56 | bool try_execute(std::function fn); 57 | 58 | // Like try_execute, but blocks until there is an empty spot to queue up for 59 | // execution. 60 | // Return false if the thread is in the process of joining (and thus cannot 61 | // accept new work). 62 | bool execute(std::function fn); 63 | 64 | // Join has been called but the thread is still executing. 65 | bool is_joining(); 66 | 67 | // Thread has fully joined and will not accept any more work. 68 | bool is_done(); 69 | 70 | // Returns the id of this mutable thread. 71 | std::thread::id get_id(); 72 | 73 | private: 74 | enum thread_state { 75 | IDLE = 0, // Ready to run 76 | RUNNING = 1, // Running a task 77 | JOINING = 2, // Running but with tasks waiting to join 78 | DONE = 3, // Running completed 79 | JOINED = 4 // Running complete and join call completed 80 | }; 81 | 82 | // Run function for the thread -- this is a wrapper around the work which 83 | // actually should get done. 84 | void run(); 85 | 86 | // Function to complete execution of the thread. 87 | void finish_run(); 88 | 89 | // Check if the thread has some action to take (either something is queued to 90 | // run or it is time to exit). 91 | bool ready_to_continue(); 92 | 93 | // Function to wait the thread until there is work to be done or the thread 94 | // should finish up. 95 | // Returns true if there is work to be done. 96 | bool thread_wait(); 97 | 98 | std::thread* t_; 99 | 100 | std::mutex thread_state_mu_; 101 | std::condition_variable thread_paused_cond_; 102 | std::atomic thread_state_; 103 | 104 | // Actively running function. 105 | std::function run_fn_; 106 | std::function queued_fn_; 107 | }; 108 | 109 | } // namespace gcl 110 | 111 | #endif 112 | -------------------------------------------------------------------------------- /include/scoped_guard.h: -------------------------------------------------------------------------------- 1 | #ifndef GCL_SCOPED_GUARD_ 2 | #define GCL_SCOPED_GUARD_ 3 | 4 | #include 5 | 6 | namespace gcl { 7 | 8 | class scoped_guard { 9 | public: 10 | explicit scoped_guard(std::function f) : f_(f) {}; 11 | explicit scoped_guard(void f()) : f_(f) {}; 12 | 13 | template 14 | explicit scoped_guard(T t) : f_(std::bind(&scoped_guard::call, t)) {}; 15 | 16 | scoped_guard(scoped_guard&& other) : f_(std::move(other.f_)) { 17 | other.dismiss(); 18 | } 19 | scoped_guard& operator=(scoped_guard&& other) { 20 | if (this != &other) { 21 | f_(); 22 | f_ = std::move(other.f_); 23 | other.dismiss(); 24 | } 25 | return *this; 26 | } 27 | 28 | ~scoped_guard() { 29 | f_(); 30 | } 31 | 32 | void dismiss() { 33 | f_ = nothing; 34 | } 35 | 36 | private: 37 | static void nothing() {}; 38 | template 39 | static void call(T t) { t(); }; 40 | 41 | scoped_guard(const scoped_guard&) = delete;; 42 | scoped_guard& operator=(const scoped_guard& other) = delete;; 43 | std::function f_; 44 | }; 45 | 46 | } // namespace gcl 47 | 48 | 49 | #endif // GCL_SCOPED_GUARD_ 50 | -------------------------------------------------------------------------------- /include/serial_executor.h: -------------------------------------------------------------------------------- 1 | // Copyright 2010 Google Inc. All Rights Reserved. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #ifndef GCL_SERIAL_EXECUTOR_ 16 | #define GCL_SERIAL_EXECUTOR_ 17 | 18 | #include 19 | 20 | #include 21 | 22 | #include 23 | #include 24 | #include 25 | 26 | namespace gcl { 27 | 28 | // Simple executor which creates a new thread for controlling and executing 29 | // parameter-free function objects. 30 | 31 | // TODO(mysen): The simple interface should allow the caller to indicate which 32 | // queueing mechanism to use to select objects to run. 33 | class serial_executor { 34 | public: 35 | // Standard executor interface which creates a FIFO queue of objects to 36 | // execute. 37 | serial_executor(); 38 | ~serial_executor(); 39 | 40 | // Simple execute command to execute a function at a convenient time. 41 | // Copies the contents of the function object and runs in the executor thread. 42 | void execute(std::function fn); 43 | 44 | private: 45 | // Queue of functions to execute. 46 | std::queue > function_queue; 47 | 48 | // Bool indicating that the class is in a state of shut-down. Used to wake up 49 | // the run thread and and finish execution. 50 | bool shutting_down; 51 | 52 | // Lock to serialize accesses to the function queue. 53 | std::mutex queue_lock; 54 | std::condition_variable queue_condvar; 55 | 56 | // Thread used by the executor to do all its work. 57 | std::thread run_thread; 58 | 59 | // Internal run function which handles all the execution logic. 60 | void run(); 61 | 62 | // Function which indicates that a job is ready to execute. 63 | // Does not do any locking, so it assumes that the caller will take ownership 64 | // of the queue_lock var before calling this. 65 | bool queue_ready(); 66 | }; 67 | 68 | } // End namespace gcl 69 | 70 | #endif // GCL_SERIAL_EXECUTOR_ 71 | -------------------------------------------------------------------------------- /include/simple_thread_pool.h: -------------------------------------------------------------------------------- 1 | // Copyright 2011 Google Inc. All Rights Reserved. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #ifndef GCL_SIMPLE_THREAD_POOL_ 16 | #define GCL_SIMPLE_THREAD_POOL_ 17 | 18 | #include 19 | 20 | #include 21 | 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include "mutable_thread.h" 27 | 28 | namespace gcl { 29 | 30 | // Basic thread aggregating class. Acts as a thread factory for mutable-thread 31 | // objects. Threads created are still owned by the thread pool until 32 | // release_thread is called. Threads can also be donated back into the pool to 33 | // allow them to be re-used by other callers. 34 | // 35 | // NOTE: the basic behavior here is to support adding/removing threads with the 36 | // ability to cap the number of threads created as well as to re-use previously 37 | // created threads if available. 38 | // 39 | // TODO: The behavior here is more like that of a thread-factory, so this will 40 | // need to be be better refined to see if there is a good way to queue up work 41 | // into the pool as well as just adding/removing threads from it (current 42 | // thinking is to have a separate "thread manager" class to handle 43 | // re-allocation of threads as well as supporting queued thread pools which 44 | // actually handle task queueing and execution). 45 | class simple_thread_pool { 46 | public: 47 | // Unbounded form of the simple_thread_pool 48 | simple_thread_pool(); 49 | 50 | // Bounded thread-pool (cap on the number of threads). 51 | simple_thread_pool(size_t min_threads, size_t max_threads); 52 | 53 | // Deleting the thread pool should wait for all threads to complete their 54 | // work. 55 | ~simple_thread_pool(); 56 | 57 | // Attempt to get a new mutable thread for execution, blocks if there is no 58 | // thread available. 59 | // Is this even a necessary function? It would end up blocking the caller for 60 | // some indefinite amount of time, which doesn't seem all that helpful. 61 | // mutable_thread* get_unused_thread(); 62 | 63 | // Non-blocking version of get_unused_thread(). This thread will be tracked 64 | // as active by the pool until the thread is either donated back to the pool 65 | // or release_thread is called. 66 | // Returns NULL if no thread is available. 67 | mutable_thread* try_get_unused_thread(); 68 | 69 | // Donates a mutable thread to the thread pool for re-use. 70 | // Returns false if the thread pool is full and cannot receive any more 71 | // threads. 72 | bool donate_thread(mutable_thread* t); 73 | 74 | // Releases a thread from being tracked by this pool. 75 | // Should only release an active thread (one created by 76 | // try_get_unused_thread). 77 | // Returns false if the thread is not active. 78 | bool release_thread(mutable_thread* t); 79 | 80 | private: 81 | // Mutex used when creating new threads. This is here to avoid race 82 | // conditions when threads are being manipulated (adding or deleting threads 83 | // from the pool). 84 | std::mutex new_thread_mu_; 85 | bool shutting_down_; 86 | std::set active_threads_; 87 | std::set unused_threads_; 88 | size_t min_threads_; 89 | size_t max_threads_; 90 | 91 | // TODO: migrate this to use the worker queue since there threads can be 92 | // interrupted. 93 | // buffer_queue > work_pool_; 94 | }; 95 | 96 | } 97 | 98 | #endif // GCL_SIMPLE_THREAD_POOL_ 99 | -------------------------------------------------------------------------------- /include/stream_mutex.h: -------------------------------------------------------------------------------- 1 | // Copyright 2011 Google Inc. All Rights Reserved. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #ifndef STREAM_MUTEX_H 16 | #define STREAM_MUTEX_H 17 | 18 | #include 19 | #include 20 | 21 | extern std::recursive_mutex* get_stream_mutex_map( void *stm_ptr ); 22 | 23 | template 24 | class stream_mutex; 25 | 26 | template 27 | class stream_guard 28 | { 29 | public: 30 | struct already_locked { }; 31 | stream_guard(stream_mutex& mtx); 32 | stream_guard(stream_mutex& mtx, already_locked); 33 | ~stream_guard(); 34 | Stream& bypass() const; 35 | private: 36 | stream_mutex& mtx_; 37 | }; 38 | 39 | template 40 | class stream_mutex 41 | { 42 | public: 43 | stream_mutex(Stream& stm) 44 | : stm_(stm), mtx_( get_stream_mutex_map( &stm ) ) { } 45 | void lock() { mtx_->lock(); } 46 | void unlock() { mtx_->unlock(); } 47 | bool try_lock() { return mtx_->try_lock(); } 48 | stream_guard hold() { return stream_guard(*this); } 49 | Stream& bypass() { return stm_; } 50 | private: 51 | Stream& stm_; 52 | std::recursive_mutex* mtx_; 53 | }; 54 | 55 | template 56 | inline stream_guard::stream_guard(stream_mutex& mtx) 57 | : mtx_(mtx) { mtx.lock(); } 58 | 59 | template 60 | inline stream_guard::stream_guard(stream_mutex& mtx, 61 | already_locked) 62 | : mtx_(mtx) { } 63 | 64 | template 65 | inline stream_guard::~stream_guard() 66 | { mtx_.unlock(); } 67 | 68 | template 69 | inline Stream& stream_guard::bypass() const 70 | { return mtx_.bypass(); } 71 | 72 | template 73 | const stream_guard& operator<<(const stream_guard& lck, 74 | const T& arg) 75 | { 76 | lck.bypass() << arg; 77 | return lck; 78 | } 79 | 80 | template 81 | const stream_guard& operator<<(const stream_guard& lck, 82 | Stream& (*arg)(Stream&)) 83 | { 84 | lck.bypass() << arg; 85 | return lck; 86 | } 87 | 88 | template 89 | const stream_guard& operator>>(const stream_guard& lck, T& arg) 90 | { 91 | lck.bypass() >> arg; 92 | return lck; 93 | } 94 | 95 | template 96 | stream_guard operator<<(stream_mutex& mtx, const T& arg) 97 | { 98 | mtx.lock(); 99 | mtx.bypass() << arg; 100 | return stream_guard(mtx, 101 | typename stream_guard::already_locked()); 102 | } 103 | 104 | template 105 | stream_guard operator<<(stream_mutex& mtx, 106 | Stream& (*arg)(Stream&)) 107 | { 108 | mtx.lock(); 109 | mtx.bypass() << arg; 110 | return stream_guard(mtx, 111 | typename stream_guard::already_locked()); 112 | } 113 | 114 | template 115 | stream_guard operator>>(stream_mutex& mtx, T& arg) 116 | { 117 | mtx.lock(); 118 | mtx.bypass() >> arg; 119 | return stream_guard(mtx, 120 | typename stream_guard::already_locked()); 121 | } 122 | 123 | extern stream_mutex mcin; 124 | extern stream_mutex mcout; 125 | extern stream_mutex mcerr; 126 | extern stream_mutex mclog; 127 | 128 | extern stream_mutex mwcin; 129 | extern stream_mutex mwcout; 130 | extern stream_mutex mwcerr; 131 | extern stream_mutex mwclog; 132 | 133 | #endif 134 | -------------------------------------------------------------------------------- /samples/blackscholes/Makefile: -------------------------------------------------------------------------------- 1 | # Put the user's flags after the defaults, so the user can override 2 | # the defaults. 3 | CppFlags := $(CPPFLAGS) 4 | AllCFlags := -pthread -Wall -Werror -g $(ALLCFLAGS) 5 | CxxFlags := $(AllCFlags) $(CXXFLAGS) 6 | CFlags := $(AllCFlags) $(CFLAGS) 7 | LdFlags := $(LDFLAGS) 8 | LdLibs := -pthread $(LDLIBS) 9 | 10 | 11 | all: blackscholes 12 | 13 | clean: 14 | find * -name '*.a' -o -name '*.o' -o -name '*.d' | xargs $(RM) 15 | 16 | blackscholes: blackscholes.o 17 | 18 | 19 | blackscholes: CppFlags += -I../../include -I. 20 | blackscholes: blackscholes.o ../../std_thread.a ../../std_mutex.a ../../std_atomic.a 21 | $(CXX) -o $@ $(LdFlags) $^ $(LOADLIBES) $(LdLibs) 22 | 23 | 24 | # Automatically rebuild when header files change: 25 | DEPEND_OPTIONS = -MMD -MP -MF "$*.d.tmp" 26 | MOVE_DEPENDFILE = then mv -f "$*.d.tmp" "$*.d"; \ 27 | else $(RM) "$*.d.tmp"; exit 1; fi 28 | 29 | %.o: %.c 30 | if $(CC) -o $@ -c $(CppFlags) $(DEPEND_OPTIONS) $(CFlags) $< ; \ 31 | $(MOVE_DEPENDFILE) 32 | 33 | %.o: %.cc 34 | if $(CXX) -o $@ -c $(CppFlags) $(DEPEND_OPTIONS) $(CxxFlags) $< ; \ 35 | $(MOVE_DEPENDFILE) 36 | 37 | # Include the generated dependency makefiles. 38 | ALL_SOURCE_BASENAMES := $(basename $(shell find * -name "*.c" -o -name "*.cc")) 39 | -include $(ALL_SOURCE_BASENAMES:%=%.d) 40 | -------------------------------------------------------------------------------- /samples/blackscholes/input.txt: -------------------------------------------------------------------------------- 1 | 4 2 | 42.00 40.00 0.1000 0.00 0.20 0.50 C 0.00 4.759423036851750055 3 | 42.00 40.00 0.1000 0.00 0.20 0.50 P 0.00 0.808600016880314021 4 | 100.00 100.00 0.0500 0.00 0.15 1.00 P 0.00 3.714602051381290071 5 | 100.00 100.00 0.0500 0.00 0.15 1.00 C 0.00 8.591659601309890704 6 | -------------------------------------------------------------------------------- /samples/dedup/Makefile: -------------------------------------------------------------------------------- 1 | # Makefile for dedup kernel 2 | 3 | PREFIX=${PARSECDIR}/pkgs/kernels/dedup/inst/${PARSECPLAT} 4 | 5 | TARGET=dedup 6 | 7 | CFLAGS += -Wall -fno-strict-aliasing -D_XOPEN_SOURCE=600 8 | LIBS += -lm 9 | 10 | DEDUP_OBJ = hashtable.o util.o dedup.o rabin.o encoder.o decoder.o mbuffer.o sha.o 11 | 12 | # Uncomment the following to enable gzip compression 13 | CFLAGS += -DENABLE_GZIP_COMPRESSION 14 | LIBS += -lz 15 | 16 | # Uncomment the following to enable bzip2 compression 17 | #CFLAGS += -DENABLE_BZIP2_COMPRESSION 18 | #LIBS += -lbz2 19 | 20 | ifdef version 21 | ifeq "$(version)" "pthreads" 22 | CFLAGS += -DENABLE_PTHREADS -pthread 23 | DEDUP_OBJ += queue.o binheap.o tree.o 24 | endif 25 | endif 26 | 27 | 28 | all: $(TARGET) 29 | 30 | .c.o: 31 | $(CC) -c $(CFLAGS) $< -o $@ 32 | 33 | $(TARGET): $(DEDUP_OBJ) 34 | $(CC) $(CFLAGS) $(LDFLAGS) -o $(TARGET) $(DEDUP_OBJ) $(LIBS) 35 | 36 | clean: 37 | rm -f *~ *.o $(TARGET) 38 | 39 | install: 40 | mkdir -p $(PREFIX)/bin 41 | cp -f $(TARGET) $(PREFIX)/bin/$(TARGET) 42 | 43 | -------------------------------------------------------------------------------- /samples/dedup/binheap.c: -------------------------------------------------------------------------------- 1 | /* Based on Data Structures and Algorithm Analysis in C (Second Edition) 2 | * by Mark Allen Weiss. 3 | * 4 | * Modified by Christian Bienia, Minlan Yu. 5 | */ 6 | 7 | #include 8 | #include 9 | #include "binheap.h" 10 | 11 | /* Macros for error handling */ 12 | #define Error( Str ) FatalError( Str ) 13 | #define FatalError( Str ) fprintf( stderr, "Binary Heap: %s\n", Str ), exit( 1 ) 14 | 15 | 16 | #define MinPQSize (16) 17 | 18 | PriorityQueue Initialize( int InitCapacity ) { 19 | PriorityQueue H; 20 | 21 | if( InitCapacity < MinPQSize ) { 22 | Error( "Priority queue size is too small" ); 23 | } 24 | 25 | H = malloc( sizeof( struct HeapStruct ) ); 26 | if( H ==NULL ) { 27 | FatalError( "Out of space!!!" ); 28 | } 29 | 30 | /* Allocate the array plus one extra for sentinel */ 31 | H->Elements = malloc( ( InitCapacity + 1 ) * sizeof( HeapElementType ) ); 32 | if( H->Elements == NULL ) { 33 | FatalError( "Out of space!!!" ); 34 | } 35 | 36 | H->Capacity = InitCapacity; 37 | H->Size = 0; 38 | H->Elements[0] = NULL; 39 | 40 | return H; 41 | } 42 | 43 | void MakeEmpty( PriorityQueue H ) { 44 | H->Size = 0; 45 | } 46 | 47 | void Insert( HeapElementType X, PriorityQueue H ) { 48 | int i; 49 | 50 | if( IsFull( H ) ) { 51 | /* double capacity of heap */ 52 | H->Capacity = 2 * H->Capacity; 53 | H->Elements = realloc( H->Elements, ( H->Capacity + 1 ) * sizeof( HeapElementType ) ); 54 | if( H->Elements == NULL ) { 55 | FatalError( "Out of space!!!" ); 56 | } 57 | } 58 | 59 | /* NOTE: H->Element[ 0 ] is a sentinel */ 60 | 61 | if (H->Size == 0) { 62 | H->Elements[1] = X; 63 | H->Size = 1; 64 | return; 65 | } 66 | 67 | H->Size++; 68 | for( i = H->Size; H->Elements[i/2]!= NULL && H->Elements[ i / 2 ]->sequence.l2num > X->sequence.l2num; i /= 2 ) { 69 | H->Elements[ i ] = H->Elements[ i / 2 ]; 70 | } 71 | H->Elements[ i ] = X; 72 | } 73 | 74 | HeapElementType DeleteMin( PriorityQueue H ) { 75 | HeapElementType MinElement, LastElement; 76 | int i, Child; 77 | 78 | if( IsEmpty( H ) ) { 79 | Error( "Priority queue is empty" ); 80 | return H->Elements[ 0 ]; 81 | } 82 | MinElement = H->Elements[ 1 ]; 83 | LastElement = H->Elements[ H->Size-- ]; 84 | 85 | for( i = 1; i * 2 <= H->Size; i = Child ) { 86 | /* Find smaller child */ 87 | Child = i * 2; 88 | if( Child != H->Size && H->Elements[ Child + 1 ]->sequence.l2num < H->Elements[ Child ]->sequence.l2num ) { 89 | Child++; 90 | } 91 | 92 | /* Percolate one level */ 93 | if( LastElement->sequence.l2num > H->Elements[ Child ]->sequence.l2num ) { 94 | H->Elements[ i ] = H->Elements[ Child ]; 95 | } else { 96 | break; 97 | } 98 | } 99 | H->Elements[ i ] = LastElement; 100 | return MinElement; 101 | } 102 | 103 | HeapElementType FindMin( PriorityQueue H ) { 104 | if( !IsEmpty( H ) ) { 105 | return H->Elements[ 1 ]; 106 | } else { 107 | //FatalError( "Priority Queue is Empty" ); 108 | return NULL; 109 | } 110 | } 111 | 112 | int IsEmpty( PriorityQueue H ) { 113 | return (H->Size == 0); 114 | } 115 | 116 | int IsFull( PriorityQueue H ) { 117 | return H->Size == H->Capacity; 118 | } 119 | 120 | int NumberElements( PriorityQueue H ) { 121 | return H->Size; 122 | } 123 | 124 | void Destroy( PriorityQueue H ) { 125 | free( H->Elements ); 126 | free( H ); 127 | } 128 | 129 | -------------------------------------------------------------------------------- /samples/dedup/binheap.h: -------------------------------------------------------------------------------- 1 | /* Based on Data Structures and Algorithm Analysis in C (Second Edition) 2 | * by Mark Allen Weiss. 3 | * 4 | * Modified by Christian Bienia, Minlan Yu. 5 | */ 6 | #ifndef _BINHEAP_H 7 | #define _BINHEAP_H 8 | 9 | #include "dedupdef.h" 10 | 11 | 12 | typedef chunk_t * HeapElementType; 13 | 14 | /* Type of a priority queue. HeapStruct is private and should not be used directly */ 15 | struct HeapStruct { 16 | int Capacity; 17 | int Size; 18 | HeapElementType * Elements; 19 | }; 20 | 21 | typedef struct HeapStruct * PriorityQueue; 22 | 23 | /* Create an empty priority queue with initial capacity 'InitCapacity' */ 24 | PriorityQueue Initialize( int InitCapacity ); 25 | 26 | /* Free all data structures of PriorityQueue */ 27 | void Destroy( PriorityQueue H ); 28 | 29 | /* Delete contents of priority queue */ 30 | void MakeEmpty( PriorityQueue H ); 31 | 32 | /* Add element X to priority queue H, automatically increases capacity if queue is full */ 33 | void Insert( HeapElementType X, PriorityQueue H ); 34 | 35 | /* Return the smallest element in the priority queue (if not empty) */ 36 | HeapElementType FindMin( PriorityQueue H ); 37 | 38 | /* Delete the smallest element in the priority queue (if not empty) */ 39 | HeapElementType DeleteMin( PriorityQueue H ); 40 | 41 | /* Check whether priority queue is empty */ 42 | int IsEmpty( PriorityQueue H ); 43 | 44 | /* Check whether priority queue is full and calling Insert would result in memory reallocation */ 45 | int IsFull( PriorityQueue H ); 46 | 47 | /* Return number of elements in priority queue */ 48 | int NumberElements( PriorityQueue H ); 49 | 50 | #endif /* _BINHEAP_H */ 51 | 52 | -------------------------------------------------------------------------------- /samples/dedup/config.h: -------------------------------------------------------------------------------- 1 | #ifndef _CONFIG_H_ 2 | #define _CONFIG_H_ 3 | 4 | //Set to 1 to statically enable parallelization with pthreads 5 | //#define ENABLE_PTHREADS 1 6 | 7 | //Set to desired number of threads per queues 8 | //The total number of queues between two pipeline stages will be 9 | //greater or equal to #threads/MAX_THREADS_PER_QUEUE 10 | #define MAX_THREADS_PER_QUEUE 4 11 | 12 | //Set to 1 to add support with statistics collection 13 | //Use argument `-v' to display statistics at end of runtime 14 | #define ENABLE_STATISTICS 1 15 | 16 | #endif //_CONFIG_H_ 17 | 18 | -------------------------------------------------------------------------------- /samples/dedup/debug.h: -------------------------------------------------------------------------------- 1 | #ifndef _DEBUG_H_ 2 | #define _DEBUG_H_ 3 | 4 | #include 5 | #include 6 | 7 | #define TRACE(fmt, msg...) { \ 8 | fprintf(stderr, "[%s] " fmt, __FUNCTION__, ##msg); \ 9 | } \ 10 | 11 | #define EXIT_TRACE(fmt, msg...) { \ 12 | TRACE(fmt, ##msg); \ 13 | exit(-1); \ 14 | } 15 | 16 | #ifndef HERE 17 | #define HERE TRACE("file %s, line %d, func %s\n", __FILE__, __LINE__, __FUNCTION__) 18 | #endif 19 | 20 | #endif //_DEBUG_H_ 21 | 22 | -------------------------------------------------------------------------------- /samples/dedup/decoder.h: -------------------------------------------------------------------------------- 1 | #ifndef _DECODER_H_ 2 | #define _DECODER_H_ 1 3 | 4 | #include "dedupdef.h" 5 | 6 | void Decode(config_t * _conf); 7 | 8 | #endif /* !_DECODER_H_ */ 9 | -------------------------------------------------------------------------------- /samples/dedup/encoder.h: -------------------------------------------------------------------------------- 1 | #ifndef _ENCODER_H_ 2 | #define _ENCODER_H_ 1 3 | 4 | void Encode(config_t * conf); 5 | 6 | #endif /* !_ENCODER_H_ */ 7 | -------------------------------------------------------------------------------- /samples/dedup/hashtable_private.h: -------------------------------------------------------------------------------- 1 | /* Copyright (C) 2002, 2004, 2007 Christopher Clark, Princeton University */ 2 | /* Parallelization by Christian Bienia */ 3 | 4 | #ifndef _HASHTABLE_PRIVATE_H_ 5 | #define _HASHTABLE_PRIVATE_H_ 6 | 7 | #include 8 | #include "config.h" 9 | 10 | #ifdef ENABLE_PTHREADS 11 | #include 12 | #endif 13 | 14 | #include "hashtable.h" 15 | 16 | 17 | /*****************************************************************************/ 18 | #ifndef STRUCT_ENTRY 19 | #define STRUCT_ENTRY 1 20 | struct hash_entry 21 | { 22 | void *k, *v; 23 | unsigned int h; 24 | struct hash_entry *next; 25 | }; 26 | #endif 27 | 28 | struct hashtable { 29 | unsigned int tablelength; 30 | struct hash_entry **table; 31 | #ifdef ENABLE_PTHREADS 32 | //Each entry in table array is protected with its own lock 33 | pthread_mutex_t *locks; 34 | #endif 35 | #ifdef ENABLE_DYNAMIC_EXPANSION 36 | unsigned int entrycount; 37 | unsigned int loadlimit; 38 | unsigned int primeindex; 39 | #endif 40 | unsigned int (*hashfn) (void *k); 41 | int (*eqfn) (void *k1, void *k2); 42 | int free_keys; 43 | }; 44 | 45 | /*****************************************************************************/ 46 | unsigned int 47 | hash(struct hashtable *h, void *k); 48 | 49 | /*****************************************************************************/ 50 | /* indexFor */ 51 | static inline unsigned int 52 | indexFor(unsigned int tablelength, unsigned int hashvalue) { 53 | return (hashvalue % tablelength); 54 | }; 55 | 56 | /* Only works if tablelength == 2^N */ 57 | /*static inline unsigned int 58 | indexFor(unsigned int tablelength, unsigned int hashvalue) 59 | { 60 | return (hashvalue & (tablelength - 1u)); 61 | } 62 | */ 63 | 64 | /*****************************************************************************/ 65 | #define freekey(X) free(X) 66 | /*define freekey(X) ; */ 67 | 68 | 69 | /*****************************************************************************/ 70 | 71 | #endif /* _HASHTABLE_PRIVATE_H_ */ 72 | 73 | /* 74 | * Copyright (c) 2002, 2007 Christopher Clark and Princeton University 75 | * All rights reserved. 76 | * 77 | * Redistribution and use in source and binary forms, with or without 78 | * modification, are permitted provided that the following conditions 79 | * are met: 80 | * 81 | * * Redistributions of source code must retain the above copyright 82 | * notice, this list of conditions and the following disclaimer. 83 | * 84 | * * Redistributions in binary form must reproduce the above copyright 85 | * notice, this list of conditions and the following disclaimer in the 86 | * documentation and/or other materials provided with the distribution. 87 | * 88 | * * Neither the name of the original author; nor the names of any contributors 89 | * may be used to endorse or promote products derived from this software 90 | * without specific prior written permission. 91 | * 92 | * 93 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 94 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 95 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 96 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER 97 | * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 98 | * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 99 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 100 | * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 101 | * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 102 | * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 103 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 104 | */ 105 | -------------------------------------------------------------------------------- /samples/dedup/mbuffer.h: -------------------------------------------------------------------------------- 1 | //Copyright 2009 Princeton University 2 | //Written by Christian Bienia 3 | 4 | /* This file contains methods and data structures to: 5 | * - Allocate and manage memory buffers 6 | * - Keep track of the usage of memory buffers and free them if necessary 7 | * - Methods to break memory buffers into smaller buffers 8 | * The purpose of all this is to eliminate memory copies by reusing allocated memory as much as possible 9 | * 10 | * Note on use in multithreaded programs: 11 | * The routines expect that the caller takes care of guaranteeing exclusive access to the arguments 12 | * passed to the routines. Access to meta data that might be shared between multiple arguments (and 13 | * hence threads) will be synchronized. Obviously the user is responsible for synchronizing access 14 | * to the contents of the buffers. 15 | * 16 | * Note on allocating and freeing: 17 | * Two memory areas need to be distinguished: The mbuffer_t structure and the buffer that is encapsulated. 18 | * The subsystem can be used with both statically and dynamically allocated mbuffer_t structures. It will 19 | * always automatically free mbuffer_t structures it has allocated itself. Manually allocated mbuffer_t 20 | * structuers also need to be freed manually. The memory for the encapsulated buffer is always freed 21 | * automatically and needs to be dynamically allocated if manual allocation is used. 22 | */ 23 | 24 | #ifndef _MBUFFER_H_ 25 | #define _MBUFFER_H_ 26 | 27 | #include 28 | 29 | //Add additional code to catch unallocated mbuffers and multiple frees 30 | //#define ENABLE_MBUFFER_CHECK 31 | 32 | #ifdef ENABLE_MBUFFER_CHECK 33 | //random number to detect properly allocated & initialized mbuffers 34 | #define MBUFFER_CHECK_MAGIC 4363097 35 | #endif 36 | 37 | //Definition of a memory control block (MCB) which tracks everything relevant for the correct use of malloc/free 38 | //Dedup breaks memory buffers into smaller memory buffers during its operation, which means that free() cannot 39 | //be called until all resulting buffers are no longer used. Furthermore we need to keep track of the original 40 | //pointer returned by malloc & co so we know which one to pass to free(). 41 | typedef struct { 42 | unsigned int i; //reference counter 43 | void *ptr; //original pointer returned by malloc that needs to be passed to free() 44 | } mcb_t; 45 | 46 | //Definition of a memory buffer 47 | typedef struct { 48 | void *ptr; //pointer to the buffer 49 | size_t n; //size of the buffer in bytes 50 | mcb_t *mcb; //meta information needed for malloc/free operations 51 | #ifdef ENABLE_MBUFFER_CHECK 52 | int check_flag; 53 | #endif 54 | } mbuffer_t; 55 | 56 | 57 | 58 | //Initialize memory buffer subsystem 59 | int mbuffer_system_init(); 60 | 61 | //Shutdown memory buffer subsystem 62 | int mbuffer_system_destroy(); 63 | 64 | //Initialize a memory buffer that has been manually or statically allocated 65 | //The mbuffer system will not attempt to free argument *m 66 | int mbuffer_create(mbuffer_t *m, size_t size); 67 | 68 | //Make a shallow copy of a memory buffer 69 | mbuffer_t *mbuffer_clone(mbuffer_t *m); 70 | 71 | //Make a deep copy of a memory buffer 72 | mbuffer_t *mbuffer_copy(mbuffer_t *m); 73 | 74 | //Free a memory buffer 75 | void mbuffer_free(mbuffer_t *m); 76 | 77 | //Resize a memory buffer 78 | //Returns 0 if the operation was successful 79 | int mbuffer_realloc(mbuffer_t *m, size_t size); 80 | 81 | //Split a memory buffer m1 into two buffers m1 and m2 at the designated location 82 | //Returns 0 if the operation was successful 83 | int mbuffer_split(mbuffer_t *m1, mbuffer_t *m2, size_t split); 84 | 85 | #endif //_MBUFFER_H_ 86 | 87 | -------------------------------------------------------------------------------- /samples/dedup/openssl/README: -------------------------------------------------------------------------------- 1 | This directory contains the subset of the OpenSSL library that implements the 2 | SHA1 functionality used by dedup. 3 | 4 | The code has been extracted from OpenSSL v0.9.8j and is covered by the OpenSSL 5 | license and the original SSLeay license. See the LICENSE files for details. 6 | 7 | - Christian Bienia 8 | 9 | -------------------------------------------------------------------------------- /samples/dedup/queue.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include "util.h" 4 | #include "queue.h" 5 | #include "config.h" 6 | 7 | #ifdef ENABLE_PTHREADS 8 | #include 9 | #endif //ENABLE_PTHREADS 10 | 11 | void queue_init(queue_t * que, size_t size, int nProducers) { 12 | #ifdef ENABLE_PTHREADS 13 | pthread_mutex_init(&que->mutex, NULL); 14 | pthread_cond_init(&que->notEmpty, NULL); 15 | pthread_cond_init(&que->notFull, NULL); 16 | #endif 17 | assert(!ringbuffer_init(&(que->buf), size)); 18 | que->nProducers = nProducers; 19 | que->nTerminated = 0; 20 | } 21 | 22 | void queue_destroy(queue_t * que) { 23 | #ifdef ENABLE_PTHREADS 24 | pthread_mutex_destroy(&que->mutex); 25 | pthread_cond_destroy(&que->notEmpty); 26 | pthread_cond_destroy(&que->notFull); 27 | #endif 28 | ringbuffer_destroy(&(que->buf)); 29 | } 30 | 31 | /* Private function which requires synchronization */ 32 | static inline int queue_isTerminated(queue_t * que) { 33 | assert(que->nTerminated <= que->nProducers); 34 | return que->nTerminated == que->nProducers; 35 | } 36 | 37 | void queue_terminate(queue_t * que) { 38 | #ifdef ENABLE_PTHREADS 39 | pthread_mutex_lock(&que->mutex); 40 | #endif 41 | que->nTerminated++; 42 | assert(que->nTerminated <= que->nProducers); 43 | #ifdef ENABLE_PTHREADS 44 | if(queue_isTerminated(que)) pthread_cond_broadcast(&que->notEmpty); 45 | pthread_mutex_unlock(&que->mutex); 46 | #endif 47 | } 48 | 49 | int queue_dequeue(queue_t *que, ringbuffer_t *buf, int limit) { 50 | int i; 51 | 52 | #ifdef ENABLE_PTHREADS 53 | pthread_mutex_lock(&que->mutex); 54 | while (ringbuffer_isEmpty(&que->buf) && !queue_isTerminated(que)) { 55 | pthread_cond_wait(&que->notEmpty, &que->mutex); 56 | } 57 | #endif 58 | if (ringbuffer_isEmpty(&que->buf) && queue_isTerminated(que)) { 59 | #ifdef ENABLE_PTHREADS 60 | pthread_mutex_unlock(&que->mutex); 61 | #endif 62 | return -1; 63 | } 64 | 65 | //NOTE: This can be optimized by copying whole segments of pointers with memcpy. However, 66 | // `limit' is typically small so the performance benefit would be negligible. 67 | for(i=0; ibuf) && !ringbuffer_isFull(buf); i++) { 68 | void *temp; 69 | int rv; 70 | 71 | temp = ringbuffer_remove(&que->buf); 72 | assert(temp!=NULL); 73 | rv = ringbuffer_insert(buf, temp); 74 | assert(rv==0); 75 | } 76 | #ifdef ENABLE_PTHREADS 77 | if(i>0) pthread_cond_signal(&que->notFull); 78 | pthread_mutex_unlock(&que->mutex); 79 | #endif 80 | return i; 81 | } 82 | 83 | int queue_enqueue(queue_t *que, ringbuffer_t *buf, int limit) { 84 | int i; 85 | 86 | #ifdef ENABLE_PTHREADS 87 | pthread_mutex_lock(&que->mutex); 88 | assert(!queue_isTerminated(que)); 89 | while (ringbuffer_isFull(&que->buf)) 90 | pthread_cond_wait(&que->notFull, &que->mutex); 91 | #else 92 | assert(!queue_isTerminated(que)); 93 | #endif 94 | 95 | //NOTE: This can be optimized by copying whole segments of pointers with memcpy. However, 96 | // `limit' is typically small so the performance benefit would be negligible. 97 | for(i=0; ibuf) && !ringbuffer_isEmpty(buf); i++) { 98 | void *temp; 99 | int rv; 100 | 101 | temp = ringbuffer_remove(buf); 102 | assert(temp!=NULL); 103 | rv = ringbuffer_insert(&que->buf, temp); 104 | assert(rv==0); 105 | } 106 | #ifdef ENABLE_PTHREADS 107 | if(i>0) pthread_cond_signal(&que->notEmpty); 108 | pthread_mutex_unlock(&que->mutex); 109 | #endif 110 | return i; 111 | } 112 | -------------------------------------------------------------------------------- /samples/dedup/queue.h: -------------------------------------------------------------------------------- 1 | #ifndef _QUEUE_H_ 2 | #define _QUEUE_H_ 3 | 4 | #include 5 | 6 | #ifdef ENABLE_PTHREADS 7 | #include 8 | #endif //ENABLE_PTHREADS 9 | 10 | //A simple ring buffer that can store a certain number of elements. 11 | //This is used for two purposes: 12 | // 1. To manage the elements inside a queue 13 | // 2. To allow queue users aggregate queue operations 14 | struct _ringbuffer_t { 15 | int head, tail; 16 | void **data; 17 | size_t size; 18 | }; 19 | 20 | typedef struct _ringbuffer_t ringbuffer_t; 21 | 22 | //A synchronized queue. 23 | //Basically just a ring buffer with some synchronization added 24 | struct _queue_t { 25 | ringbuffer_t buf; 26 | int nProducers; 27 | int nTerminated; 28 | #ifdef ENABLE_PTHREADS 29 | pthread_mutex_t mutex; 30 | pthread_cond_t notEmpty, notFull; 31 | #endif //ENABLE_PTHREADS 32 | }; 33 | 34 | typedef struct _queue_t queue_t; 35 | 36 | 37 | 38 | /* 39 | * Some simple inline functions to work with ring buffers 40 | */ 41 | 42 | //Initialize a ring buffer 43 | static inline int ringbuffer_init(ringbuffer_t *buf, size_t size) { 44 | //NOTE: We have to allocate one extra element because one element will be unusable (we need to distinguish between full and empty). 45 | buf->data = (void **)malloc(sizeof(void*) * (size+1)); 46 | buf->size = (size+1); 47 | buf->head = 0; 48 | buf->tail = 0; 49 | 50 | return (buf->data==NULL); 51 | } 52 | 53 | //Destroy a ring buffer 54 | static inline int ringbuffer_destroy(ringbuffer_t *buf) { 55 | free(buf->data); 56 | return 0; 57 | } 58 | 59 | //Returns true if and only if the ring buffer is empty 60 | static inline int ringbuffer_isEmpty(ringbuffer_t *buf) { 61 | return (buf->tail == buf->head); 62 | } 63 | 64 | //Returns true if and only if the ring buffer is full 65 | static inline int ringbuffer_isFull(ringbuffer_t *buf) { 66 | return (buf->head == (buf->tail-1+buf->size)%buf->size); 67 | } 68 | 69 | //Get an element from a ringbuffer 70 | //Returns NULL if buffer is empty 71 | static inline void *ringbuffer_remove(ringbuffer_t *buf) { 72 | void *ptr; 73 | 74 | if(ringbuffer_isEmpty(buf)) { 75 | ptr = NULL; 76 | } else { 77 | ptr = buf->data[buf->tail]; 78 | buf->tail++; 79 | if(buf->tail >= buf->size) buf->tail = 0; 80 | } 81 | 82 | return ptr; 83 | } 84 | 85 | //Put an element into a ringbuffer 86 | //Returns 0 if the operation succeeded 87 | static inline int ringbuffer_insert(ringbuffer_t *buf, void *ptr) { 88 | if(ringbuffer_isFull(buf)) return -1; 89 | buf->data[buf->head] = ptr; 90 | buf->head++; 91 | if(buf->head == buf->size) buf->head = 0; 92 | 93 | return 0; 94 | } 95 | 96 | 97 | 98 | /* 99 | * Queue interface 100 | */ 101 | 102 | void queue_init(queue_t * que, size_t size, int nProducers); 103 | void queue_destroy(queue_t * que); 104 | 105 | void queue_terminate(queue_t * que); 106 | 107 | int queue_dequeue(queue_t *que, ringbuffer_t *buf, int limit); 108 | int queue_enqueue(queue_t *que, ringbuffer_t *buf, int limit); 109 | 110 | #endif //_QUEUE_H_ 111 | 112 | -------------------------------------------------------------------------------- /samples/dedup/rabin.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #include "dedupdef.h" 6 | #include "rabin.h" 7 | 8 | #undef PRINT 9 | 10 | /* Functions to compute rabin fingerprints */ 11 | 12 | //u32int *rabintab = 0; 13 | //u32int *rabinwintab = 0; 14 | //static u32int irrpoly = 0x759ddb9f; 15 | static u32int irrpoly = 0x45c2b6a1; 16 | 17 | uint32_t bswap32(x) uint32_t x; { 18 | return ((x << 24) & 0xff000000 ) | 19 | ((x << 8) & 0x00ff0000 ) | 20 | ((x >> 8) & 0x0000ff00 ) | 21 | ((x >> 24) & 0x000000ff ); 22 | } 23 | 24 | static u32int fpreduce(u32int x, u32int irr) { 25 | int i; 26 | 27 | for(i=32; i!=0; i--){ 28 | if(x >> 31){ 29 | x <<= 1; 30 | x ^= irr; 31 | }else 32 | x <<= 1; 33 | } 34 | return x; 35 | } 36 | 37 | static void fpmkredtab(u32int irr, int s, u32int *tab) { 38 | u32int i; 39 | 40 | for(i=0; i<256; i++) 41 | tab[i] = fpreduce(i<>24]; 51 | for(i=1; i>24]; 53 | return winval; 54 | } 55 | 56 | static void fpmkwinredtab(u32int irr, int winlen, u32int * rabintab, u32int *rabinwintab) { 57 | u32int i; 58 | 59 | for(i=0; i<256; i++) 60 | rabinwintab[i] = fpwinreduce(irr, winlen, i, rabintab); 61 | return; 62 | } 63 | 64 | void rabininit(int winlen, u32int * rabintab, u32int * rabinwintab) { 65 | //rabintab = malloc(256*sizeof rabintab[0]); 66 | //rabinwintab = malloc(256*sizeof rabintab[0]); 67 | fpmkredtab(irrpoly, 0, rabintab); 68 | fpmkwinredtab(irrpoly, winlen, rabintab, rabinwintab); 69 | return; 70 | } 71 | 72 | int rabinseg(uchar *p, int n, int winlen, u32int * rabintab, u32int * rabinwintab) { 73 | int i; 74 | u32int h; 75 | u32int x; 76 | 77 | USED(winlen); 78 | if(n < NWINDOW) 79 | return n; 80 | 81 | h = 0; 82 | for(i=0; i> 24; 84 | h = (h<<8)|p[i]; 85 | h ^= rabintab[x]; 86 | } 87 | if((h & RabinMask) == 0) 88 | return i; 89 | while(i> 24; 93 | h <<= 8; 94 | h |= p[i++]; 95 | h ^= rabintab[x]; 96 | if((h & RabinMask) == 0) 97 | return i; 98 | } 99 | return n; 100 | } 101 | 102 | -------------------------------------------------------------------------------- /samples/dedup/rabin.h: -------------------------------------------------------------------------------- 1 | #ifndef _RABIN_H_ 2 | #define _RABIN_H_ 3 | 4 | /* Define USED macro */ 5 | #define USED(x) { ulong y __attribute__ ((unused)); y = (ulong)x; } 6 | 7 | enum { 8 | NWINDOW = 32, 9 | MinSegment = 1024, 10 | RabinMask = 0xfff, // must be less than <= 0x7fff 11 | }; 12 | 13 | void rabininit(int, u32int*, u32int*); 14 | 15 | int rabinseg(uchar*, int, int, u32int*, u32int*); 16 | 17 | #endif //_RABIN_H_ 18 | 19 | -------------------------------------------------------------------------------- /samples/dedup/sha.c: -------------------------------------------------------------------------------- 1 | #include "openssl/sha.h" 2 | 3 | #define SHA_1 4 | #include "openssl/sha_locl.h" 5 | 6 | void SHA1_Digest(const void *data, size_t len, unsigned char *digest) { 7 | SHA_CTX sha; 8 | 9 | SHA1_Init(&sha); 10 | SHA1_Update(&sha, data, len); 11 | SHA1_Final(digest, &sha); 12 | } 13 | 14 | -------------------------------------------------------------------------------- /samples/dedup/sha.h: -------------------------------------------------------------------------------- 1 | /* Proxy SHA1 header file for PARSEC Benchmark Suite 2 | * Written by Christian Bienia 3 | * 4 | * This file includes the OpenSSL headers and defines some macros so that 5 | * the extracted SHA1 code can be used without the rest of the OpenSSL 6 | * package. 7 | */ 8 | #ifndef _SHA_H_ 9 | #define _SHA_H_ 10 | 11 | #include "openssl/sha.h" 12 | 13 | /* SHA1 length is 20 bytes(160 bites) */ 14 | #define SHA1_LEN 20 15 | 16 | void SHA1_Digest(const void *data, size_t len, unsigned char *digest); 17 | 18 | #endif //_SHA_H_ 19 | 20 | -------------------------------------------------------------------------------- /samples/dedup/tree.c: -------------------------------------------------------------------------------- 1 | /* Based on Data Structures and Algorithm Analysis in C (Second Edition) 2 | * by Mark Allen Weiss. 3 | * 4 | * Modified by Minlan Yu. 5 | */ 6 | #include 7 | #include 8 | 9 | #include "tree.h" 10 | #include "util.h" 11 | 12 | #ifdef ENABLE_DMALLOC 13 | #include 14 | #endif //ENABLE_DMALLOC 15 | 16 | struct TreeNode * pmin; 17 | 18 | SearchTree TreeMakeEmpty( SearchTree T ) { 19 | if( T != NULL ) { 20 | TreeMakeEmpty( T->Left ); 21 | TreeMakeEmpty( T->Right ); 22 | free( T ); 23 | pmin = NULL; 24 | } 25 | return NULL; 26 | } 27 | 28 | Position TreeFind( int value, SearchTree T ) { 29 | if( T == NULL ) return NULL; 30 | if( value < T->Element.l1num ) { 31 | return TreeFind( value, T->Left ); 32 | } else { 33 | if( value > T->Element.l1num ) { 34 | return TreeFind(value, T->Right ); 35 | } else { 36 | return T; 37 | } 38 | } 39 | } 40 | 41 | Position TreeFindMin( SearchTree T ) { 42 | if (pmin != NULL) return pmin; 43 | if( T == NULL ) { 44 | return NULL; 45 | } else { 46 | if( T->Left == NULL ) { 47 | return T; 48 | } else { 49 | return TreeFindMin( T->Left ); 50 | } 51 | } 52 | } 53 | 54 | Position TreeFindMax( SearchTree T ) { 55 | if( T != NULL ) { 56 | while( T->Right != NULL ) { 57 | T = T->Right; 58 | } 59 | } 60 | return T; 61 | } 62 | 63 | SearchTree TreeInsert( TreeElementType X, SearchTree T ) { 64 | if (pmin!= NULL && X.l1num < pmin->Element.l1num) pmin = NULL; 65 | if( T == NULL ) { 66 | /* Create and return a one-node tree */ 67 | T = malloc( sizeof( struct TreeNode ) ); 68 | if( T == NULL ) { 69 | perror( "Out of space!!!" ); 70 | } else { 71 | T->Element = X; 72 | T->Left = T->Right = NULL; 73 | } 74 | } else { 75 | if( X.l1num < T->Element.l1num ) { 76 | T->Left = TreeInsert( X, T->Left ); 77 | } else { 78 | if( X.l1num > T->Element.l1num ) { 79 | T->Right = TreeInsert( X, T->Right ); 80 | } 81 | /* Else X is in the tree already; we'll do nothing */ 82 | } 83 | } 84 | return T; /* Do not forget this line!! */ 85 | } 86 | 87 | SearchTree TreeDelete( TreeElementType X, SearchTree T ) { 88 | Position TmpCell; 89 | 90 | if (pmin != NULL && X.l1num == pmin->Element.l1num) pmin = NULL; 91 | 92 | if( T == NULL ) { 93 | perror( "Element not found" ); 94 | } else { 95 | if( X.l1num < T->Element.l1num ) { 96 | /* Go left */ 97 | T->Left = TreeDelete( X, T->Left ); 98 | } else { 99 | if( X.l1num > T->Element.l1num ) { 100 | /* Go right */ 101 | T->Right = TreeDelete( X, T->Right ); 102 | } else { 103 | /* Found element to be deleted */ 104 | if( T->Left && T->Right ) { 105 | /* Two children */ 106 | /* Replace with smallest in right subtree */ 107 | TmpCell = TreeFindMin( T->Right ); 108 | T->Element = TmpCell->Element; 109 | T->Right = TreeDelete( T->Element, T->Right ); 110 | } else { 111 | /* One or zero children */ 112 | TmpCell = T; 113 | if( T->Left == NULL ) { 114 | /* Also handles 0 children */ 115 | T = T->Right; 116 | } else { 117 | if( T->Right == NULL ) { 118 | T = T->Left; 119 | } 120 | } 121 | free( TmpCell ); 122 | } 123 | } 124 | } 125 | } 126 | 127 | return T; 128 | } 129 | 130 | TreeElementType Retrieve( Position P ) { 131 | return P->Element; 132 | } 133 | 134 | -------------------------------------------------------------------------------- /samples/dedup/tree.h: -------------------------------------------------------------------------------- 1 | /* Based on Data Structures and Algorithm Analysis in C (Second Edition) 2 | * by Mark Allen Weiss. 3 | * 4 | * Modified by Minlan Yu. 5 | */ 6 | #ifndef _TREE_H_ 7 | #define _TREE_H_ 8 | 9 | #include "binheap.h" 10 | 11 | struct tree_element { 12 | sequence_number_t l1num; 13 | PriorityQueue queue; 14 | }; 15 | 16 | typedef struct tree_element TreeElementType; 17 | 18 | struct TreeNode; 19 | typedef struct TreeNode *Position; 20 | typedef struct TreeNode *SearchTree; 21 | 22 | struct TreeNode { 23 | TreeElementType Element; 24 | SearchTree Left; 25 | SearchTree Right; 26 | }; 27 | 28 | SearchTree TreeMakeEmpty( SearchTree T ); 29 | Position TreeFind( int value, SearchTree T ); 30 | Position TreeFindMin( SearchTree T ); 31 | Position TreeFindMax( SearchTree T ); 32 | SearchTree TreeInsert( TreeElementType X, SearchTree T ); 33 | SearchTree TreeDelete( TreeElementType X, SearchTree T ); 34 | TreeElementType TreeRetrieve( Position P ); 35 | 36 | #endif /* _TREE_H_ */ 37 | 38 | -------------------------------------------------------------------------------- /samples/dedup/util.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #include "util.h" 6 | 7 | 8 | 9 | int xread(int sd, void *buf, size_t len) { 10 | char *p = (char *)buf; 11 | size_t nrecv = 0; 12 | size_t rv; 13 | 14 | while (nrecv < len) { 15 | rv = read(sd, p, len - nrecv); 16 | if (0 > rv && errno == EINTR) 17 | continue; 18 | if (0 > rv) 19 | return -1; 20 | if (0 == rv) 21 | return 0; 22 | nrecv += rv; 23 | p += rv; 24 | } 25 | return nrecv; 26 | } 27 | 28 | int xwrite(int sd, const void *buf, size_t len) { 29 | char *p = (char *)buf; 30 | size_t nsent = 0; 31 | ssize_t rv; 32 | 33 | while (nsent < len) { 34 | rv = write(sd, p, len - nsent); 35 | if (0 > rv && (errno == EINTR || errno == EAGAIN)) 36 | continue; 37 | if (0 > rv) 38 | return -1; 39 | nsent += rv; 40 | p += rv; 41 | } 42 | return nsent; 43 | } 44 | 45 | int read_header(int fd, byte *compress_type) { 46 | int checkbit; 47 | 48 | assert(compress_type != NULL); 49 | 50 | if (xread(fd, &checkbit, sizeof(int)) < 0){ 51 | return -1; 52 | } 53 | if (checkbit != CHECKBIT) { 54 | printf("format error!\n"); 55 | return -1; 56 | } 57 | 58 | if (xread(fd, compress_type, sizeof(byte)) < 0){ 59 | return -1; 60 | } 61 | 62 | return 0; 63 | } 64 | 65 | int write_header(int fd, byte compress_type) { 66 | int checkbit = CHECKBIT; 67 | if (xwrite(fd, &checkbit, sizeof(int)) < 0){ 68 | return -1; 69 | } 70 | 71 | if (xwrite(fd, &compress_type, sizeof(byte)) < 0){ 72 | return -1; 73 | } 74 | return 0; 75 | } 76 | 77 | -------------------------------------------------------------------------------- /samples/dedup/util.h: -------------------------------------------------------------------------------- 1 | #ifndef _UTIL_H_ 2 | #define _UTIL_H_ 3 | 4 | #include "dedupdef.h" 5 | 6 | /* File I/O with error checking */ 7 | int xread(int sd, void *buf, size_t len); 8 | int xwrite(int sd, const void *buf, size_t len); 9 | 10 | /* Process file header */ 11 | int read_header(int fd, byte *compress_type); 12 | int write_header(int fd, byte compress_type); 13 | 14 | #endif //_UTIL_H_ 15 | 16 | -------------------------------------------------------------------------------- /src/barrier.cc: -------------------------------------------------------------------------------- 1 | // Copyright 2010 Google Inc. All Rights Reserved. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #include 16 | 17 | #include "barrier.h" 18 | 19 | namespace gcl { 20 | 21 | barrier::barrier(std::ptrdiff_t num_threads) 22 | : thread_count_(num_threads), num_waiting_(0) { 23 | if (num_threads < 0) { 24 | throw std::invalid_argument("num_threads is negative"); 25 | } 26 | num_to_leave_ = 0; // std::atomic_init(&num_to_leave_, 0); 27 | } 28 | 29 | barrier::~barrier() { 30 | while (!all_threads_exited()) { 31 | // Don't destroy this object if threads have not yet exited 32 | // arrive_and_drop(). This can occur when a thread calls 33 | // arrive_and_drop() followed by the destructor - the waiting threads 34 | // may be scheduled to wake up, but not yet have exited. 35 | // 36 | // NOTE - on pthread systems, could add a yield call here 37 | } 38 | } 39 | 40 | // These methods could be implemented as C++11 lambdas, but are written as 41 | // member functions for C++98 compatibility. 42 | bool barrier::all_threads_exited() { 43 | return num_to_leave_ == 0; 44 | } 45 | 46 | bool barrier::all_threads_waiting() { 47 | return num_waiting_ == thread_count_; 48 | } 49 | 50 | void barrier::arrive_and_wait() { 51 | { 52 | std::unique_lock lock(mutex_); 53 | // TODO(alasdair): This can deadlock - fix it. 54 | idle_.wait(lock, std::bind(&barrier::all_threads_exited, this)); 55 | ++num_waiting_; 56 | if (num_waiting_ == thread_count_) { 57 | num_to_leave_ = thread_count_; 58 | ready_.notify_all(); 59 | } else { 60 | ready_.wait(lock, std::bind(&barrier::all_threads_waiting, this)); 61 | } 62 | if (num_to_leave_ == 1) { 63 | num_waiting_ = 0; 64 | idle_.notify_all(); 65 | } 66 | } 67 | --num_to_leave_; 68 | } 69 | 70 | void barrier::arrive_and_drop() { 71 | { 72 | std::unique_lock lock(mutex_); 73 | idle_.wait(lock, std::bind(&barrier::all_threads_exited, this)); 74 | if (--thread_count_ == 0) { 75 | throw std::invalid_argument("All threads have left"); 76 | } 77 | if (num_waiting_ == thread_count_) { 78 | num_to_leave_ = thread_count_; 79 | ready_.notify_all(); 80 | } 81 | } 82 | } 83 | 84 | } // End namespace gcl 85 | -------------------------------------------------------------------------------- /src/countdown_latch.cc: -------------------------------------------------------------------------------- 1 | // Copyright 2009 Google Inc. All Rights Reserved. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #include 16 | #include 17 | 18 | #include "countdown_latch.h" 19 | 20 | namespace gcl { 21 | 22 | countdown_latch::countdown_latch(unsigned int count) 23 | : count_(count) { 24 | } 25 | 26 | countdown_latch::~countdown_latch() { 27 | // Normally we expect count_ == 0, but in some cases a user might create a 28 | // countdown_latch but abandon it later. To allow that abandonment we don't 29 | // check count here. 30 | } 31 | 32 | void countdown_latch::wait() { 33 | std::unique_lock lock(condition_mutex_); 34 | while(count_ > 0) { 35 | condition_.wait(lock); 36 | } 37 | } 38 | 39 | void countdown_latch::count_down() { 40 | std::lock_guard lock(condition_mutex_); 41 | if (count_ <= 0) { 42 | throw std::system_error(std::make_error_code(std::errc::invalid_argument)); 43 | } 44 | if (--count_ == 0) { 45 | condition_.notify_all(); 46 | } 47 | } 48 | 49 | } // End namespace gcl 50 | -------------------------------------------------------------------------------- /src/debug.cc: -------------------------------------------------------------------------------- 1 | // Copyright 2011 Google Inc. All Rights Reserved. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #include "debug.h" 16 | 17 | namespace gcl { 18 | 19 | stream_mutex dbg_stream(std::cerr); 20 | 21 | } // namespace gcl 22 | -------------------------------------------------------------------------------- /src/flex_barrier.cc: -------------------------------------------------------------------------------- 1 | // Copyright 2010 Google Inc. All Rights Reserved. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #include 16 | #include 17 | 18 | #include "flex_barrier.h" 19 | 20 | namespace gcl { 21 | 22 | flex_barrier::~flex_barrier() { 23 | while (!all_threads_exited()) { 24 | // Don't destroy this object if threads have not yet exited 25 | // arrive_and_wait(). This can occur when a thread calls 26 | // arrive_and_wait() followed by the destructor - the waiting threads 27 | // may be scheduled to wake up, but not yet have exited. 28 | // 29 | // NOTE - on pthread systems, could add a yield call here 30 | } 31 | std::cerr << "destroying with - thread_count_ = " << thread_count_ 32 | << ", num_waiting_ " << num_waiting_ << "\n"; 33 | } 34 | 35 | // These methods could be implemented as C++11 lambdas, but are written as 36 | // member functions for C++98 compatibility. 37 | bool flex_barrier::all_threads_exited() { 38 | return num_to_leave_ == 0; 39 | } 40 | 41 | bool flex_barrier::all_threads_waiting() { 42 | return num_waiting_ == thread_count_; 43 | } 44 | 45 | void flex_barrier::arrive_and_wait() { 46 | std::unique_lock lock(mutex_); 47 | idle_.wait(lock, std::bind(&flex_barrier::all_threads_exited, this)); 48 | ++num_waiting_; 49 | if (num_waiting_ == thread_count_) { 50 | num_to_leave_ = thread_count_; 51 | on_countdown(); 52 | ready_.notify_all(); 53 | } else { 54 | ready_.wait(lock, std::bind(&flex_barrier::all_threads_waiting, this)); 55 | } 56 | // The last thread to leave resets the thread_count_ for the next phase. 57 | if (num_to_leave_ == 1) { 58 | thread_count_ = new_thread_count_; 59 | num_waiting_ = 0; 60 | idle_.notify_all(); 61 | } 62 | --num_to_leave_; 63 | } 64 | 65 | void flex_barrier::arrive_and_drop() { 66 | std::unique_lock lock(mutex_); 67 | idle_.wait(lock, std::bind(&flex_barrier::all_threads_exited, this)); 68 | if (thread_count_ == 0) { 69 | throw std::invalid_argument("All threads have left"); 70 | } 71 | --thread_count_; 72 | if (num_waiting_ == thread_count_) { 73 | num_to_leave_ = thread_count_; 74 | on_countdown(); 75 | ready_.notify_all(); 76 | } 77 | } 78 | 79 | void flex_barrier::on_countdown() { 80 | reset(completion_fn_()); 81 | } 82 | 83 | void flex_barrier::reset(std::ptrdiff_t num_threads) { 84 | if (num_threads == 0) { 85 | throw std::invalid_argument("num_threads is 0"); 86 | } 87 | // TODO(alasdair): Consider adding a check that we are either in the 88 | // completion function, or have not yet called wait() 89 | if (num_threads > 0) { 90 | new_thread_count_ = num_threads; 91 | } else { 92 | new_thread_count_ = thread_count_; 93 | } 94 | } 95 | 96 | } // End namespace gcl 97 | -------------------------------------------------------------------------------- /src/latch.cc: -------------------------------------------------------------------------------- 1 | // Copyright 2011 Google Inc. All Rights Reserved. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | #include 15 | 16 | 17 | #include "latch.h" 18 | 19 | #include 20 | #include 21 | 22 | namespace gcl { 23 | 24 | latch::latch(std::ptrdiff_t count) : count_(count) { 25 | waiting_ = 0; // std::atomic_init(&waiting_, 0); 26 | } 27 | 28 | latch::~latch() { 29 | while (waiting_ > 0) { 30 | // Don't destroy this object if threads have not yet exited wait(). This can 31 | // occur when a thread calls count_down() followed by the destructor - the 32 | // waiting threads may be scheduled to wake up, but have not yet have exited. 33 | // 34 | // NOTE - on pthread systems, could add a yield call here 35 | } 36 | } 37 | 38 | void latch::wait() const { 39 | ++waiting_; 40 | { 41 | std::unique_lock lock(condition_mutex_); 42 | while(count_ > 0) { 43 | condition_.wait(lock); 44 | } 45 | } 46 | --waiting_; 47 | } 48 | 49 | bool latch::is_ready() const noexcept { 50 | std::unique_lock lock(condition_mutex_); 51 | return (count_ == 0); 52 | } 53 | 54 | void latch::count_down(std::ptrdiff_t n) { 55 | std::lock_guard lock(condition_mutex_); 56 | if (count_ - n < 0) { 57 | throw std::logic_error("internal count == 0"); 58 | } 59 | count_ -= n; 60 | if (count_ == 0) { 61 | condition_.notify_all(); 62 | } 63 | } 64 | 65 | void latch::count_down_and_wait() { 66 | ++waiting_; 67 | { 68 | std::unique_lock lock(condition_mutex_); 69 | if (count_ == 0) { 70 | throw std::logic_error("internal count == 0"); 71 | } 72 | if (--count_ == 0) { 73 | condition_.notify_all(); 74 | } else { 75 | while(count_ > 0) { 76 | condition_.wait(lock); 77 | } 78 | } 79 | } 80 | --waiting_; 81 | } 82 | 83 | } // End namespace gcl 84 | -------------------------------------------------------------------------------- /src/serial_executor.cc: -------------------------------------------------------------------------------- 1 | // Copyright 2011 Google Inc. All Rights Reserved. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #include 16 | 17 | #include 18 | 19 | #include 20 | #include 21 | #include 22 | 23 | #include "serial_executor.h" 24 | 25 | namespace gcl { 26 | 27 | serial_executor::serial_executor() 28 | : shutting_down(false), 29 | run_thread(std::bind(&serial_executor::run, this)) {} 30 | 31 | serial_executor::~serial_executor() { 32 | // Try to do a safe shutdown of the executor. 33 | // This will still wait for the currently executing task to complete, but 34 | // drops any future execution. 35 | queue_lock.lock(); 36 | shutting_down = true; 37 | while (!function_queue.empty()) { 38 | function_queue.pop(); 39 | } 40 | 41 | queue_condvar.notify_one(); 42 | queue_lock.unlock(); 43 | run_thread.join(); 44 | } 45 | 46 | void serial_executor::execute(std::function fn) { 47 | std::lock_guard guard(queue_lock); 48 | function_queue.push(fn); 49 | queue_condvar.notify_one(); 50 | } 51 | 52 | // Nothing fancy in the run interface (except that it is quite wasteful 53 | // of CPU). Probably should move this to use a notification. 54 | void serial_executor::run() { 55 | while (!shutting_down) { 56 | std::unique_lock ul(queue_lock); 57 | queue_condvar.wait(ul, std::bind(&serial_executor::queue_ready, this)); 58 | 59 | // Queue can be ready if the executor is shutting down and the runner must 60 | // finish up to exit. 61 | if (!shutting_down) { 62 | std::function run_function = function_queue.front(); 63 | function_queue.pop(); 64 | ul.unlock(); 65 | 66 | run_function(); 67 | } 68 | } 69 | } 70 | 71 | bool serial_executor::queue_ready() { 72 | return !function_queue.empty() || shutting_down; 73 | } 74 | 75 | } // End namespace gcl 76 | -------------------------------------------------------------------------------- /src/simple_thread_pool.cc: -------------------------------------------------------------------------------- 1 | // Copyright 2011 Google Inc. All Rights Reserved. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #include 16 | #include 17 | #include 18 | 19 | #include 20 | 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include "mutable_thread.h" 26 | 27 | #include "simple_thread_pool.h" 28 | 29 | namespace gcl { 30 | 31 | simple_thread_pool::simple_thread_pool() 32 | : shutting_down_(false), 33 | min_threads_(0), 34 | max_threads_(std::numeric_limits::max()) {} 35 | 36 | // Bounded thread-pool (cap on the number of threads). 37 | simple_thread_pool::simple_thread_pool(size_t min_threads, size_t max_threads) 38 | : shutting_down_(false), min_threads_(min_threads), 39 | max_threads_(max_threads) { 40 | for (size_t i = 0; i < min_threads; ++i) { 41 | unused_threads_.insert(new mutable_thread()); 42 | } 43 | } 44 | 45 | simple_thread_pool::~simple_thread_pool() { 46 | { 47 | // Lock the new thread mutex to prevent new any sort of operations on this 48 | // pool. 49 | std::unique_lock ul(new_thread_mu_); 50 | shutting_down_ = true; 51 | } 52 | 53 | // Should be in shutting_down_ state, so it's safe to kill stuff. 54 | std::set::iterator iter; 55 | for (iter = active_threads_.begin(); 56 | iter != active_threads_.end(); ++iter) { 57 | mutable_thread* t = *iter; 58 | t->join(); 59 | delete t; 60 | } 61 | 62 | for (iter = unused_threads_.begin(); 63 | iter != unused_threads_.end(); ++iter) { 64 | mutable_thread* t = *iter; 65 | t->join(); 66 | delete t; 67 | } 68 | } 69 | 70 | mutable_thread* simple_thread_pool::try_get_unused_thread() { 71 | mutable_thread* next_thread = NULL; 72 | 73 | { 74 | std::unique_lock ul(new_thread_mu_); 75 | if (!shutting_down_) { 76 | if (unused_threads_.empty()) { 77 | if (active_threads_.size() < max_threads_) { 78 | next_thread = new mutable_thread(); 79 | active_threads_.insert(next_thread); 80 | } // else do nothing, we're out of threads 81 | } else { 82 | next_thread = *unused_threads_.begin(); 83 | active_threads_.insert(next_thread); 84 | unused_threads_.erase(unused_threads_.find(next_thread)); 85 | } 86 | } 87 | } 88 | 89 | return next_thread; 90 | } 91 | 92 | bool simple_thread_pool::donate_thread(mutable_thread* t) { 93 | std::unique_lock ul(new_thread_mu_); 94 | // Check that the pool doesn't already own the thread 95 | std::set::iterator active_iter = active_threads_.find(t); 96 | if (active_iter != active_threads_.end()) { 97 | active_threads_.erase(active_iter); 98 | unused_threads_.insert(t); 99 | return true; 100 | } else if (unused_threads_.find(t) == unused_threads_.end()) { 101 | unused_threads_.insert(t); 102 | return true; 103 | } 104 | return false; 105 | } 106 | 107 | bool simple_thread_pool::release_thread(mutable_thread* t) { 108 | std::unique_lock ul(new_thread_mu_); 109 | std::set::iterator iter = active_threads_.find(t); 110 | if (iter != active_threads_.end()) { 111 | active_threads_.erase(iter); 112 | return true; 113 | } 114 | 115 | return false; 116 | } 117 | 118 | 119 | } // namespace gcl 120 | -------------------------------------------------------------------------------- /src/stream_mutex.cc: -------------------------------------------------------------------------------- 1 | // Copyright 2012 Google Inc. All Rights Reserved. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #include 16 | 17 | #include "stream_mutex.h" 18 | 19 | std::recursive_mutex* get_stream_mutex_map( void *stm_ptr ) 20 | { 21 | static std::mutex map_mutex; 22 | static std::unordered_map stream_map( 19 ); 23 | std::lock_guard _(map_mutex); 24 | std::recursive_mutex*& mtx_ptr = stream_map[stm_ptr]; 25 | if (!mtx_ptr) 26 | mtx_ptr = new std::recursive_mutex; 27 | return mtx_ptr; 28 | } 29 | 30 | stream_mutex mcin(std::cin); 31 | stream_mutex mcout(std::cout); 32 | stream_mutex mcerr(std::cerr); 33 | stream_mutex mclog(std::clog); 34 | 35 | stream_mutex mwcin(std::wcin); 36 | stream_mutex mwcout(std::wcout); 37 | stream_mutex mwcerr(std::wcerr); 38 | stream_mutex mwclog(std::wclog); 39 | -------------------------------------------------------------------------------- /testing/barrier_test.cc: -------------------------------------------------------------------------------- 1 | // Copyright 2010 Google Inc. All Rights Reserved. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | // This file is a test of the barrier class 16 | 17 | #include 18 | #include 19 | 20 | #include 21 | #include 22 | 23 | #include "gmock/gmock.h" 24 | 25 | #include "barrier.h" 26 | 27 | using testing::_; 28 | 29 | using gcl::barrier; 30 | 31 | // TODO(alasdair): Update kNumCycles when the potential deadlock in 32 | // arrive_and_drop has been fixed. 33 | static int kNumCycles = 1; 34 | static int kNumThreads = 5; 35 | static int kInvalidCount = -1; 36 | 37 | class BarrierTest : public testing::Test { 38 | }; 39 | 40 | // Verifies that we cannot create a barrier with an illegal number of 41 | // threads. 42 | TEST_F(BarrierTest, InvalidConstructorArg) { 43 | try { 44 | barrier b(kInvalidCount); 45 | FAIL(); 46 | } catch (std::invalid_argument expected) { 47 | } 48 | } 49 | 50 | static void WaitForBarrier(barrier* b, int n_cycles) { 51 | for (int i = 0; i < n_cycles; ++i) { 52 | b->arrive_and_wait(); 53 | } 54 | } 55 | 56 | static void Drop(barrier* b) { 57 | b->arrive_and_drop(); 58 | } 59 | 60 | TEST_F(BarrierTest, ArriveAndWait) { 61 | barrier b(kNumThreads); 62 | std::thread* threads[kNumThreads]; 63 | for (int i = 0; i < kNumThreads; i++) { 64 | threads[i] = new std::thread(std::bind(WaitForBarrier, &b, 1)); 65 | } 66 | for (int i = 0; i < kNumThreads; i++) { 67 | threads[i]->join(); 68 | } 69 | for (int i = 0; i < kNumThreads; i++) { 70 | delete threads[i]; 71 | } 72 | } 73 | 74 | TEST_F(BarrierTest, ArriveAndWaitMultipleCycles) { 75 | barrier b(kNumThreads); 76 | std::thread* threads[kNumThreads]; 77 | for (int i = 0; i < kNumThreads; i++) { 78 | threads[i] = new std::thread(std::bind(WaitForBarrier, &b, kNumCycles)); 79 | } 80 | for (int i = 0; i < kNumThreads; i++) { 81 | threads[i]->join(); 82 | } 83 | for (int i = 0; i < kNumThreads; i++) { 84 | delete threads[i]; 85 | } 86 | } 87 | 88 | TEST_F(BarrierTest, ArriveAndDrop) { 89 | barrier b(kNumThreads); 90 | std::thread* threads[kNumThreads]; 91 | for (int i = 0; i < kNumThreads; i++) { 92 | if (i % 2 == 0) { 93 | threads[i] = new std::thread(std::bind(WaitForBarrier, &b, kNumCycles)); 94 | } else { 95 | threads[i] = new std::thread(std::bind(Drop, &b)); 96 | } 97 | } 98 | for (int i = 0; i < kNumThreads; i++) { 99 | threads[i]->join(); 100 | } 101 | for (int i = 0; i < kNumThreads; i++) { 102 | delete threads[i]; 103 | } 104 | } 105 | -------------------------------------------------------------------------------- /testing/blockable_thread.cc: -------------------------------------------------------------------------------- 1 | // Copyright 2010 Google Inc. All Rights Reserved. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #include "blockable_thread.h" 16 | #include "test_mutex.h" 17 | 18 | ThreadBlocker::ThreadBlocker() : count_(1), block_latch_(1), start_latch_(1) { 19 | } 20 | 21 | ThreadBlocker::ThreadBlocker(int count) 22 | : count_(count), 23 | block_latch_(1), 24 | start_latch_(1) { 25 | } 26 | 27 | void ThreadBlocker::SetThread(thread::id id) { 28 | // Verify that id is null. A ThreadBlocker can only be associated 29 | // with one thread. 30 | assert(id_ == thread::id()); 31 | id_ = id; 32 | } 33 | 34 | void ThreadBlocker::Block() { 35 | THREAD_DBG << "ThreadBlocker::Block " << id_ << " count = " << count_ << ENDL; 36 | if (this_thread::get_id() == id_) { 37 | if (--count_ == 0) { 38 | THREAD_DBG << "waiting on latch" << ENDL; 39 | block_latch_.wait(); 40 | } 41 | } 42 | } 43 | 44 | void ThreadBlocker::Unlock() { 45 | block_latch_.count_down(); 46 | } 47 | 48 | void ThreadBlocker::WaitToStart() { 49 | start_latch_.wait(); 50 | } 51 | 52 | void ThreadBlocker::Start() { 53 | start_latch_.count_down(); 54 | } 55 | -------------------------------------------------------------------------------- /testing/blockable_thread.h: -------------------------------------------------------------------------------- 1 | // Copyright 2010 Google Inc. All Rights Reserved. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #ifndef STD_TESTING_THREADBLOCKER_ 16 | #define STD_TESTING_THREADBLOCKER_ 17 | 18 | #include 19 | 20 | #include 21 | #include 22 | 23 | #include "countdown_latch.h" 24 | #include "test_mutex.h" 25 | 26 | using gcl::countdown_latch; 27 | 28 | // A ThreadBlocker will block when it is invoked from a given thread, 29 | // but will not block when invoked from other threads. It enables the 30 | // creation of test cases where two similar actions are performed in 31 | // two separate threads. If the threads are A and B then a typical 32 | // sequence might be: 33 | // 34 | // Start an operation in thread A. Waiting until thread A is blocked 35 | // by the ThreadBlocker. 36 | // 37 | // Perform the same operation in thread B. The operation will not block. 38 | // 39 | // Resume thread A when thread B has finished. Verify the results. 40 | // 41 | // A ThreadBlocker is used in conjunciton with a BlockableThread. 42 | // Sample useage would be: 43 | // 44 | // void Action(ThreadBlocker& blocker) { 45 | // ... 46 | // // Will only block when called from blockable thread created below. 47 | // blocker.Block(); 48 | // } 49 | // 50 | // void Test() { 51 | // ThreadBlocker blocker(); 52 | // BlockableThread thr(std::bind(Action, blocker), &blocker); 53 | // blocker.Start(); 54 | // 55 | // // Wait until 'thr' is blocked. 56 | // ThreadMonitor::GetInstance()->WaitUntilBlocked(thr.get_id()); 57 | // // Invoke Action() in another thread. Will not block. 58 | // ... 59 | // blocker.Unlock(); 60 | // thr.join(); 61 | // 62 | class ThreadBlocker { 63 | public: 64 | // Creates a ThreadBlocker that will block on the first call to 65 | // Block() 66 | ThreadBlocker(); 67 | 68 | // Creates a ThreadBlocker that will block on the count'th call to 69 | // Block() 70 | explicit ThreadBlocker(int count); 71 | 72 | // Starts the BlockableThread associated with this ThreadBlocker 73 | void Start(); 74 | 75 | // Blocks the caller iff it is invoked from the associated 76 | // BlockableThread, and the count has been reached. Note that 77 | // subsequent calls to this method (after count has been reached) 78 | // will not block. 79 | void Block(); 80 | 81 | // Unlocks the blocked thread. If called before the thread has 82 | // blocked, the unlock operation is a no-op, and the thread will 83 | // still subsequently block when the conditions are met. 84 | void Unlock(); 85 | 86 | private: 87 | friend class BlockableThread; 88 | void SetThread(thread::id id); 89 | void WaitToStart(); 90 | 91 | thread::id id_; 92 | mutex count_mutex_; 93 | int count_; 94 | countdown_latch block_latch_; 95 | countdown_latch start_latch_; 96 | }; 97 | 98 | // A thread used in conjunction with a ThreadBlocker 99 | class BlockableThread : public thread { 100 | public: 101 | // Creates a new BlockableThread associated with the given 102 | // ThreadBlocker. A ThreadBlocker should only be associated with one thread. 103 | template explicit BlockableThread(F f, ThreadBlocker* blocker); 104 | private: 105 | void init(ThreadBlocker* blocker) { 106 | blocker->SetThread(this_thread::get_id()); 107 | blocker->WaitToStart(); 108 | f_(); 109 | } 110 | std::function f_; 111 | 112 | // Disallow copy and assign 113 | BlockableThread(const BlockableThread&); 114 | void operator=(const BlockableThread&); 115 | }; 116 | 117 | template 118 | BlockableThread::BlockableThread(F f, ThreadBlocker* blocker) 119 | : thread(std::bind(&BlockableThread::init, this, blocker)), 120 | f_(f) { 121 | } 122 | 123 | #endif // STD_TESTING_THREADBLOCKER_ 124 | -------------------------------------------------------------------------------- /testing/called_task.h: -------------------------------------------------------------------------------- 1 | // Copyright 2011 Google Inc. All Rights Reserved. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #include 16 | #include 17 | 18 | #include "mutable_thread.h" 19 | 20 | namespace gcl { 21 | 22 | // Helper class which executes a basic add function and blocks the thread until 23 | // the ready-count of threads is hit (this is very much like a barrier-closure 24 | // in behavior but with a little bit more test-functionality). 25 | struct Called { 26 | Called(int ready_count) { 27 | //std::atomic_init(&this->ready_count, ready_count); 28 | this->ready_count = ready_count; 29 | count = 0; // std::atomic_init(&count, 0); 30 | } 31 | 32 | void run() { 33 | std::unique_lock wait_lock(ready_lock); 34 | count.fetch_add(1, std::memory_order_relaxed); 35 | ready_condvar.notify_one(); 36 | } 37 | 38 | // Blocking wait function which returns when count reaches ready_count 39 | void wait() { 40 | std::unique_lock wait_lock(ready_lock); 41 | ready_condvar.wait(wait_lock, std::bind(&Called::is_done, this)); 42 | } 43 | 44 | void update_count(int new_ready_count) { 45 | int expected = 2; 46 | while (!std::atomic_compare_exchange_weak(&ready_count, 47 | &expected, 48 | new_ready_count)) {} 49 | } 50 | 51 | std::atomic count; 52 | 53 | std::atomic ready_count; 54 | std::mutex ready_lock; 55 | std::condition_variable ready_condvar; 56 | 57 | private: 58 | bool is_done() { 59 | return ready_count.load() == count.load(std::memory_order_relaxed); 60 | } 61 | }; 62 | 63 | } // namespace gcl 64 | -------------------------------------------------------------------------------- /testing/cleanup_assert.h: -------------------------------------------------------------------------------- 1 | // Copyright 2011 Google Inc. All Rights Reserved. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #ifndef CLEANUP_ASSERT_H 16 | #define CLEANUP_ASSERT_H 17 | 18 | /* WARNING: 19 | 20 | Only the last parameter to these macros are evaluated only once. 21 | Make sure arguments to all other parameters are idempotent. 22 | 23 | */ 24 | 25 | #define CLEANUP_ASSERT_LT(a, b, clean) \ 26 | do if ( (a) >= (b) ) { clean ASSERT_LT(a, b); } while (0) 27 | #define CLEANUP_ASSERT_LE(a, b, clean) \ 28 | do if ( (a) > (b) ) { clean ASSERT_LE(a, b); } while (0) 29 | #define CLEANUP_ASSERT_EQ(a, b, clean) \ 30 | do if ( (a) != (b) ) { clean ASSERT_EQ(a, b); } while (0) 31 | #define CLEANUP_ASSERT_GE(a, b, clean) \ 32 | do if ( (a) < (b) ) { clean ASSERT_GE(a, b); } while (0) 33 | #define CLEANUP_ASSERT_GT(a, b, clean) \ 34 | do if ( (a) <= (b) ) { clean ASSERT_GT(a, b); } while (0) 35 | #define CLEANUP_ASSERT_TRUE(b, clean) \ 36 | do if ( !(b) ) { clean ASSERT_TRUE(b); } while (0) 37 | #define CLEANUP_ASSERT_FALSE(b, clean) \ 38 | do if ( (b) ) { clean ASSERT_FALSE(b); } while (0) 39 | 40 | #endif 41 | -------------------------------------------------------------------------------- /testing/countdown_latch_test.cc: -------------------------------------------------------------------------------- 1 | // Copyright 2010 Google Inc. All Rights Reserved. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | // Unit tests for countdown_latch 16 | 17 | #include 18 | 19 | #include 20 | 21 | #include "countdown_latch.h" 22 | #include "test_mutex.h" 23 | 24 | #include "gmock/gmock.h" 25 | 26 | using namespace std; 27 | using testing::_; 28 | 29 | class CountdownLatchTest : public testing::Test { 30 | }; 31 | 32 | void WaitForLatch(countdown_latch& latch) { 33 | std::cerr << "WaitForLatch " << this_thread::get_id() << "\n"; 34 | latch.wait(); 35 | std::cerr << "WaitForLatch waited " << this_thread::get_id() << "\n"; 36 | EXPECT_EQ(latch.get_count(), 0); 37 | } 38 | 39 | void WaitForLatchAndDecrement(countdown_latch& to_wait, 40 | countdown_latch& decrement) { 41 | to_wait.wait(); 42 | decrement.count_down(); 43 | EXPECT_EQ(to_wait.get_count(), 0); 44 | EXPECT_EQ(decrement.get_count(), 0); 45 | } 46 | 47 | void DecrementAndWaitForLatch(countdown_latch& decrement, 48 | countdown_latch& to_wait) { 49 | decrement.count_down(); 50 | to_wait.wait(); 51 | EXPECT_EQ(to_wait.get_count(), 0); 52 | EXPECT_EQ(decrement.get_count(), 0); 53 | } 54 | 55 | // Tests two threads waiting on a single countdown_latch 56 | TEST_F(CountdownLatchTest, TwoThreads) { 57 | countdown_latch latch(2); 58 | thread t1(std::bind(WaitForLatch, std::ref(latch))); 59 | thread t2(std::bind(WaitForLatch, std::ref(latch))); 60 | std::cerr << "Counting down " << this_thread::get_id() << "\n"; 61 | latch.count_down(); 62 | std::cerr << "Counting down " << this_thread::get_id() << "\n"; 63 | latch.count_down(); 64 | t1.join(); 65 | t2.join(); 66 | } 67 | 68 | // Tests two threads waiting on a countdown_latch that has already 69 | // been decremented. 70 | TEST_F(CountdownLatchTest, TwoThreadsPreDecremented) { 71 | countdown_latch latch(2); 72 | latch.count_down(); 73 | latch.count_down(); 74 | thread t1(std::bind(WaitForLatch, std::ref(latch))); 75 | thread t2(std::bind(WaitForLatch, std::ref(latch))); 76 | t1.join(); 77 | t2.join(); 78 | } 79 | 80 | // Tests two threads waiting and decrementing two latches 81 | TEST_F(CountdownLatchTest, TwoThreadsTwoLatches) { 82 | countdown_latch first(1); 83 | countdown_latch second(1); 84 | thread t1(std::bind( 85 | WaitForLatchAndDecrement, std::ref(first), std::ref(second))); 86 | thread t2(std::bind( 87 | DecrementAndWaitForLatch, std::ref(first), std::ref(second))); 88 | t1.join(); 89 | t2.join(); 90 | } 91 | -------------------------------------------------------------------------------- /testing/dynarray_test.cc: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include "dynarray.h" 5 | 6 | std::dynarray a_global(32); 7 | 8 | void dump( const std::dynarray< int > & source ) 9 | { 10 | std::dynarray< int >::const_iterator src = source.begin(); 11 | for ( ; src != source.end(); src++ ) 12 | std::cout << " " << *src; 13 | std::cout << std::endl; 14 | } 15 | void lowrap( std::dynarray< int > & target, 16 | const std::dynarray< int > & source ) 17 | { 18 | dump( source ); 19 | 20 | std::dynarray< int > sorted( source ); 21 | dump( sorted ); 22 | 23 | std::sort( sorted.begin(), sorted.end() ); 24 | dump( sorted ); 25 | 26 | const int* srt = &sorted.front(); 27 | std::dynarray< int >::iterator tgt( target.begin() ); 28 | for ( ; tgt != target.end(); tgt++ ) { 29 | *tgt = *srt; 30 | if ( srt == &sorted.back() ) 31 | srt = &sorted.front(); 32 | else 33 | srt++; 34 | } 35 | dump( target ); 36 | } 37 | int main() { 38 | std::dynarray< int > alpha(8); 39 | std::dynarray< int > gamma(3); 40 | for ( std::dynarray< int >::size_type i = 0; i < gamma.size(); i++ ) 41 | gamma[i] = 4 - i; 42 | lowrap( alpha, gamma ); 43 | int sum = 0; 44 | for ( std::dynarray< int >::size_type i = 0; i < alpha.size(); i++ ) 45 | sum += alpha.at(i); 46 | 47 | if ( sum != 23 ) 48 | return 1; 49 | return 0; 50 | } 51 | -------------------------------------------------------------------------------- /testing/iterator_queue_test.cc: -------------------------------------------------------------------------------- 1 | // Copyright 2010 Google Inc. All Rights Reserved. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | // This file is a test of the iterator_queue class 16 | 17 | #include 18 | 19 | #include 20 | 21 | #include 22 | 23 | #include "countdown_latch.h" 24 | #include 25 | #include "iterator_queue.h" 26 | 27 | #include "gmock/gmock.h" 28 | 29 | using testing::_; 30 | 31 | using std::vector; 32 | using gcl::iterator_queue; 33 | using gcl::countdown_latch; 34 | 35 | class IteratorQueueTest : public testing::Test { 36 | }; 37 | 38 | typedef std::vector int_vector; 39 | typedef std::vector latch_vector; 40 | 41 | // Verifies that we can create a queue from a basic vector, and read 42 | // its values. 43 | TEST_F(IteratorQueueTest, BasicRead) { 44 | int_vector values; 45 | values.push_back(1); 46 | values.push_back(2); 47 | values.push_back(3); 48 | values.push_back(4); 49 | iterator_queue queue(values.begin(), values.end()); 50 | for(size_t i = 0; i < values.size(); i++) { 51 | ASSERT_FALSE(queue.is_closed()); 52 | ASSERT_EQ(values[i], queue.pop()); 53 | } 54 | ASSERT_TRUE(queue.is_closed()); 55 | try { 56 | queue.pop(); 57 | FAIL(); 58 | } catch (gcl::closed_error expected) { 59 | } 60 | } 61 | 62 | static void GetAndBlock(iterator_queue* queue, 63 | countdown_latch* started) { 64 | while (!queue->is_closed()) { 65 | countdown_latch* latch = queue->pop(); 66 | started->count_down(); 67 | latch->wait(); 68 | } 69 | } 70 | 71 | // Verifies that we can read from a queue in multiple threads 72 | TEST_F(IteratorQueueTest, ThreadedRead) { 73 | latch_vector latches; 74 | for (int i = 0; i < 4; i++) { 75 | latches.push_back(new countdown_latch(1)); 76 | } 77 | iterator_queue queue(latches.begin(), latches.end()); 78 | countdown_latch latch1(1); 79 | countdown_latch latch2(1); 80 | countdown_latch latch3(1); 81 | std::thread thread1(std::bind(GetAndBlock, &queue, &latch1)); 82 | std::thread thread2(std::bind(GetAndBlock, &queue, &latch2)); 83 | std::thread thread3(std::bind(GetAndBlock, &queue, &latch3)); 84 | latch1.wait(); 85 | latch2.wait(); 86 | latch3.wait(); 87 | // At this point the three threads have all popped a value from the 88 | // queue, and will be blocked in GetAndBlock. There should be one 89 | // value remaining. Pop that and verify that the queue is closed. 90 | ASSERT_FALSE(queue.is_closed()); 91 | queue.pop(); 92 | ASSERT_TRUE(queue.is_closed()); 93 | 94 | // Unblock the first three threads. They should all find that the 95 | // queue is closed, and will terminate. 96 | for(size_t i = 0; i < 3; i++) { 97 | latches[i]->count_down(); 98 | } 99 | thread1.join(); 100 | thread2.join(); 101 | thread3.join(); 102 | latches[3]->count_down(); 103 | for(size_t i = 0; i < 4; i++) { 104 | delete latches[i]; 105 | } 106 | } 107 | -------------------------------------------------------------------------------- /testing/latch_test.cc: -------------------------------------------------------------------------------- 1 | // Copyright 2013 Google Inc. All Rights Reserved. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | // Unit tests for latch 16 | 17 | #include 18 | 19 | #include 20 | #include 21 | #include "scoped_guard.h" 22 | 23 | #include "latch.h" 24 | 25 | #include "gmock/gmock.h" 26 | 27 | using namespace std; 28 | using gcl::latch; 29 | using gcl::scoped_guard; 30 | using testing::_; 31 | 32 | class LatchTest : public testing::Test { 33 | }; 34 | 35 | void WaitForLatch(const latch& latch) { 36 | std::cerr << "WaitForLatch " << this_thread::get_id() << "\n"; 37 | latch.wait(); 38 | std::cerr << "WaitForLatch waited " << this_thread::get_id() << "\n"; 39 | } 40 | 41 | void TryWaitForLatch(const latch& test_latch, latch& started_latch, atomic_bool* finished) { 42 | started_latch.count_down(1); 43 | while (!test_latch.is_ready()) { 44 | // spin; 45 | } 46 | *finished = true; 47 | } 48 | 49 | void WaitForLatchAndDecrement(const latch& to_wait, 50 | latch& decrement) { 51 | to_wait.wait(); 52 | decrement.count_down(); 53 | EXPECT_TRUE(to_wait.is_ready()); 54 | EXPECT_TRUE(to_wait.is_ready()); 55 | } 56 | 57 | void DecrementAndWaitForLatch(latch& decrement, 58 | const latch& to_wait) { 59 | decrement.count_down(); 60 | to_wait.wait(); 61 | EXPECT_TRUE(to_wait.is_ready()); 62 | EXPECT_TRUE(decrement.is_ready()); 63 | } 64 | 65 | // Tests two threads waiting on a single latch 66 | TEST_F(LatchTest, TwoThreads) { 67 | latch latch(2); 68 | thread t1(std::bind(WaitForLatch, std::ref(latch))); 69 | thread t2(std::bind(WaitForLatch, std::ref(latch))); 70 | std::cerr << "Counting down " << this_thread::get_id() << "\n"; 71 | latch.count_down(1); 72 | std::cerr << "Counting down " << this_thread::get_id() << "\n"; 73 | latch.count_down(1); 74 | t1.join(); 75 | t2.join(); 76 | } 77 | 78 | // Tests two threads try-waiting on a single latch 79 | TEST_F(LatchTest, TwoThreadsTryWait) { 80 | latch test_latch(1); 81 | latch started_latch(2); 82 | atomic_bool finished1; 83 | finished1 = false; 84 | atomic_bool finished2; 85 | finished2 = false; 86 | 87 | thread t1(std::bind(TryWaitForLatch, 88 | std::ref(test_latch), 89 | std::ref(started_latch), 90 | &finished1)); 91 | thread t2(std::bind(TryWaitForLatch, 92 | std::ref(test_latch), 93 | std::ref(started_latch), 94 | &finished2)); 95 | started_latch.wait(); 96 | ASSERT_FALSE(finished1); 97 | ASSERT_FALSE(finished2); 98 | test_latch.count_down(1); 99 | t1.join(); 100 | t2.join(); 101 | ASSERT_TRUE(finished1); 102 | ASSERT_TRUE(finished2); 103 | } 104 | 105 | // Tests two threads waiting on a latch that has already 106 | // been decremented. 107 | TEST_F(LatchTest, TwoThreadsPreDecremented) { 108 | latch latch(2); 109 | latch.count_down(1); 110 | latch.count_down(1); 111 | thread t1(std::bind(WaitForLatch, std::ref(latch))); 112 | thread t2(std::bind(WaitForLatch, std::ref(latch))); 113 | t1.join(); 114 | t2.join(); 115 | } 116 | 117 | // Tests two threads waiting and decrementing two latches 118 | TEST_F(LatchTest, TwoThreadsTwoLatches) { 119 | latch first(1); 120 | latch second(1); 121 | thread t1(std::bind( 122 | WaitForLatchAndDecrement, std::ref(first), std::ref(second))); 123 | thread t2(std::bind( 124 | DecrementAndWaitForLatch, std::ref(first), std::ref(second))); 125 | t1.join(); 126 | t2.join(); 127 | } 128 | -------------------------------------------------------------------------------- /testing/lock_free_buffer_queue_test.cc: -------------------------------------------------------------------------------- 1 | // Copyright 2013 Google Inc. All Rights Reserved. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #include "lock_free_buffer_queue.h" 16 | #include "queue_base_test.h" 17 | 18 | using gcl::lock_free_buffer_queue; 19 | 20 | const int kSmall = 4; 21 | const int kLarge = 1000; 22 | 23 | class LockFreeBufferQueueTest 24 | : 25 | public testing::Test 26 | { 27 | }; 28 | 29 | // Verifies that we cannot create a queue of size zero 30 | TEST_F(LockFreeBufferQueueTest, InvalidArg0) { 31 | try { 32 | lock_free_buffer_queue body(0); 33 | FAIL(); 34 | } catch (std::invalid_argument expected) { 35 | } catch (...) { 36 | FAIL(); 37 | } 38 | } 39 | 40 | // Verify single try push/pop operations. 41 | TEST_F(LockFreeBufferQueueTest, SingleTry) { 42 | lock_free_buffer_queue q(1); 43 | seq_try_fill(1, 1, &q); 44 | seq_try_drain(1, 1, &q); 45 | } 46 | 47 | // Verify multiple try push/pop operations. 48 | TEST_F(LockFreeBufferQueueTest, MultipleTry) { 49 | lock_free_buffer_queue q(kSmall); 50 | seq_try_fill(kSmall, 1, &q); 51 | seq_try_drain(kSmall, 1, &q); 52 | } 53 | 54 | // Verifies that we can create a queue from iterators. 55 | TEST_F(LockFreeBufferQueueTest, CreateFromIterators) { 56 | std::vector values; 57 | for ( int i = 1; i <= kSmall; ++i ) 58 | values.push_back(i); 59 | ASSERT_EQ(static_cast(kSmall), values.size()); 60 | lock_free_buffer_queue q(values.size(), values.begin(), values.end()); 61 | seq_try_drain(kSmall, 1, &q); 62 | } 63 | 64 | // Verifies that we cannot create a queue from iterators where the 65 | // maximum size is less than that defined by the iterators 66 | TEST_F(LockFreeBufferQueueTest, InvalidIterators) { 67 | std::vector values; 68 | values.push_back(1); 69 | values.push_back(2); 70 | values.push_back(3); 71 | try { 72 | lock_free_buffer_queue q(2, values.begin(), values.end()); 73 | FAIL(); 74 | } catch (std::invalid_argument expected) { 75 | } catch (...) { 76 | } 77 | } 78 | 79 | // Verify that try_pop fails when the queue is empty, but succeeds when a new 80 | // element is added. 81 | TEST_F(LockFreeBufferQueueTest, TryPopEmpty) { 82 | lock_free_buffer_queue q(kSmall); 83 | seq_try_empty(&q); 84 | } 85 | 86 | // Verify that try_push succeeds until we exceed the size limit 87 | TEST_F(LockFreeBufferQueueTest, TryPushFull) { 88 | lock_free_buffer_queue q(kSmall); 89 | seq_try_full(kSmall, &q); 90 | } 91 | -------------------------------------------------------------------------------- /testing/map_reduce_test.cc: -------------------------------------------------------------------------------- 1 | // Copyright 2012 Google Inc. All Rights Reserved. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #include 16 | #include 17 | #include 18 | 19 | #include "buffer_queue.h" 20 | #include 21 | #include "map_reduce.h" 22 | #include "map_reduce_helpers.h" 23 | #include "queue_base.h" 24 | #include "simple_thread_pool.h" 25 | #include "gtest/gtest.h" 26 | #include 27 | 28 | using gcl::buffer_queue; 29 | using gcl::map_reduce_options; 30 | using gcl::map_reduce; 31 | using gcl::mapper; 32 | using gcl::queue_front; 33 | using gcl::queue_front_iter; 34 | using gcl::queue_base; 35 | using gcl::queue_wrapper; 36 | using gcl::reducer; 37 | using gcl::simple_thread_pool; 38 | 39 | class BucketizingMapper { 40 | public: 41 | typedef int input_type; 42 | typedef int key_type; 43 | typedef float value_type; 44 | 45 | void start() {} 46 | 47 | template 48 | void map(const int& input, 49 | OutIter output) { 50 | output = std::pair(input % 10, static_cast(input)); 51 | } 52 | 53 | void flush() {} 54 | }; 55 | 56 | class AveragingReducer { 57 | public: 58 | typedef int key_type; 59 | typedef float value_type; 60 | typedef float output_value_type; 61 | 62 | void start(unsigned int shard_id) {} 63 | 64 | template 65 | void reduce( 66 | const int& key, 67 | InIter* value_start, 68 | InIter* value_end, 69 | OutIter output) { 70 | double value_sum = 0.0; 71 | int num_values = 0; 72 | for (InIter* value_iter = value_start; 73 | (*value_iter) != (*value_end); ++(*value_iter)) { 74 | value_sum += *(*value_iter); 75 | ++num_values; 76 | } 77 | 78 | std::cout << "reduce output " << key << " " << value_sum / num_values << std::endl; 79 | output = std::pair(key, value_sum / num_values); 80 | } 81 | void flush() {} 82 | }; 83 | 84 | class MapReduceTest : public testing::Test { 85 | }; 86 | 87 | TEST_F(MapReduceTest, TestMR) { 88 | 89 | typedef gcl::blocking_map > blocking_output_map; 90 | typedef gcl::map_output_iter output_iter; 91 | typedef queue_front_iter > input_iter; 92 | 93 | blocking_output_map out_map; 94 | map_reduce_options opts; 95 | opts.num_mappers = 3; 96 | opts.num_reduce_shards = 19; 97 | opts.num_reducers = 5; 98 | opts.thread_pool = new simple_thread_pool; 99 | 100 | output_iter out_iter(&out_map); 101 | opts.out = out_iter; 102 | 103 | map_reduce mr(opts); 106 | buffer_queue input_queue(1000); 107 | input_queue.push(10); // avg = 10.0 108 | 109 | input_queue.push(12); 110 | input_queue.push(12); 111 | input_queue.push(22); 112 | input_queue.push(22); // avg = 17.0 113 | 114 | // avg = 103.0 115 | for (int i = 0; i < 20; ++i) input_queue.push(103); 116 | 117 | // avg = 2754.0 118 | for (int i = 0; i < 20; ++i) input_queue.push(1004); 119 | for (int i = 0; i < 20; ++i) input_queue.push(2004); 120 | for (int i = 0; i < 40; ++i) input_queue.push(4004); 121 | 122 | // avg = 1025 123 | for (int i = 0; i < 40; ++i) input_queue.push(1005); 124 | for (int i = 0; i < 40; ++i) input_queue.push(1015); 125 | for (int i = 0; i < 40; ++i) input_queue.push(1025); 126 | for (int i = 0; i < 40; ++i) input_queue.push(1035); 127 | for (int i = 0; i < 40; ++i) input_queue.push(1045); 128 | input_queue.close(); 129 | queue_wrapper > input_wrap(input_queue); 130 | mr.run(input_wrap.begin(), input_wrap.end()); 131 | 132 | // Check the outputs! 133 | EXPECT_EQ(10.0, out_map[0]); 134 | EXPECT_EQ(17.0, out_map[2]); 135 | EXPECT_EQ(103.0, out_map[3]); 136 | EXPECT_EQ(2754.0, out_map[4]); 137 | EXPECT_EQ(1025.0, out_map[5]); 138 | } 139 | -------------------------------------------------------------------------------- /testing/mutable_thread_test.cc: -------------------------------------------------------------------------------- 1 | // Copyright 2011 Google Inc. All Rights Reserved. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | // Basic test of the mutable_thread class. 16 | 17 | #include 18 | 19 | #include 20 | 21 | #include 22 | #include 23 | #include 24 | 25 | #include "called_task.h" 26 | #include "mutable_thread.h" 27 | 28 | #include "gmock/gmock.h" 29 | 30 | namespace gcl { 31 | namespace { 32 | 33 | //using std::bind; 34 | 35 | TEST(MutableThreadTest, TestExecute) { 36 | Called called(2); 37 | mutable_thread t; 38 | 39 | // Queue up 2 units of work, though first unit will not complete until the 40 | // count is incremented by the test thread (wait blocks). 41 | t.execute(std::bind(&Called::run, &called)); 42 | t.execute(std::bind(&Called::wait, &called)); 43 | // This call should block until the run command completes since the queue is 44 | // only 2 entries deep. 45 | t.execute(std::bind(&Called::run, &called)); 46 | EXPECT_EQ(1, called.count.load()); 47 | 48 | // Then release the thread by calling wait() and let the count go up. 49 | called.run(); 50 | 51 | std::this_thread::sleep_for(std::chrono::milliseconds(1)); 52 | 53 | // Count should go up to 3 (the 2 queued calls and the one run() call here). 54 | EXPECT_EQ(3, called.count.load()); 55 | } 56 | 57 | TEST(MutableThreadTest, TestJoin) { 58 | Called called(1); 59 | 60 | mutable_thread t; 61 | t.execute(std::bind(&Called::run, &called)); 62 | called.wait(); 63 | 64 | // Join should complete at this point. 65 | t.join(); 66 | 67 | EXPECT_TRUE(t.is_done()); 68 | } 69 | 70 | } 71 | } // namespace gcl 72 | -------------------------------------------------------------------------------- /testing/race_test.cc: -------------------------------------------------------------------------------- 1 | // Copyright 2010 Google Inc. All Rights Reserved. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | // This file is a test for races and race detectors. 16 | // TODO: extend this test: 17 | // - Add more tests with races. 18 | // - Add tests on which race detectors may potentially give false warnings. 19 | // - Add tests that use dynamic annotations. 20 | 21 | #include 22 | 23 | #include 24 | 25 | #include "test_mutex.h" 26 | 27 | #include "gmock/gmock.h" 28 | 29 | static void IncrementArg1(int *arg) { 30 | (*arg)++; 31 | } 32 | 33 | static void IncrementArg1LockAndUnlockArg2(int *arg1, mutex *mu) { 34 | (*arg1)++; 35 | mu->lock(); 36 | mu->unlock(); 37 | } 38 | 39 | static void SleepLockAndUnlockArg2IncrementArg1(int *arg1, mutex *mu) { 40 | this_thread::sleep_for(chrono::milliseconds(1000)); 41 | mu->lock(); 42 | mu->unlock(); 43 | (*arg1)++; 44 | } 45 | 46 | // Simple race. 47 | TEST(ThreadTest, SimpleDataRaceTest) { 48 | int racey = 0; 49 | thread thr1(std::bind(IncrementArg1, &racey)); 50 | thread thr2(std::bind(IncrementArg1, &racey)); 51 | thr1.join(); 52 | thr2.join(); 53 | EXPECT_EQ(racey, 2); // With a tiny probability this will fail. 54 | } 55 | 56 | // Two racey accesses, lock/unlock between them. 57 | // Pure happens-before detectors will not find this race. 58 | TEST(ThreadTest, DataRaceWithLockInBetween) { 59 | int racey = 0; 60 | mutex mu; 61 | thread thr1(std::bind(IncrementArg1LockAndUnlockArg2, &racey, &mu)); 62 | thread thr2(std::bind(SleepLockAndUnlockArg2IncrementArg1, &racey, &mu)); 63 | thr1.join(); 64 | thr2.join(); 65 | EXPECT_EQ(racey, 2); // With a tiny probability this will fail. 66 | } 67 | -------------------------------------------------------------------------------- /testing/scoped_guard_test.cc: -------------------------------------------------------------------------------- 1 | #include "scoped_guard.h" 2 | 3 | #include "gtest/gtest.h" 4 | 5 | using namespace gcl; 6 | 7 | int i; 8 | 9 | class ScopedGuardTest : public testing::Test { 10 | protected: 11 | void SetUp() { 12 | i = 0; 13 | } 14 | 15 | }; 16 | 17 | void inc_i() { 18 | i++; 19 | } 20 | 21 | class incrementer { 22 | public: 23 | void operator()() { 24 | inc_i(); 25 | } 26 | }; 27 | 28 | void scoped_no_inc() { 29 | scoped_guard g(inc_i); 30 | g.dismiss(); 31 | } 32 | 33 | TEST_F(ScopedGuardTest, Basics) { 34 | EXPECT_EQ(i, 0); 35 | { 36 | scoped_guard g(inc_i); 37 | EXPECT_EQ(i, 0); 38 | } 39 | EXPECT_EQ(i, 1); 40 | { 41 | scoped_guard g(inc_i); 42 | EXPECT_EQ(i, 1); 43 | g.dismiss(); 44 | EXPECT_EQ(i, 1); 45 | } 46 | EXPECT_EQ(i, 1); 47 | } 48 | 49 | TEST_F(ScopedGuardTest, Callable) { 50 | incrementer c; 51 | EXPECT_EQ(i, 0); 52 | { 53 | scoped_guard g(c); 54 | EXPECT_EQ(i, 0); 55 | } 56 | EXPECT_EQ(i, 1); 57 | { 58 | scoped_guard g(c); 59 | EXPECT_EQ(i, 1); 60 | g.dismiss(); 61 | EXPECT_EQ(i, 1); 62 | } 63 | EXPECT_EQ(i, 1); 64 | } 65 | 66 | template 67 | scoped_guard make_guard(T t) { 68 | scoped_guard s(t); 69 | return s; 70 | } 71 | 72 | TEST_F(ScopedGuardTest, Factory) { 73 | EXPECT_EQ(i, 0); 74 | { 75 | auto g = make_guard(inc_i); 76 | EXPECT_EQ(i, 0); 77 | } 78 | EXPECT_EQ(i, 1); 79 | { 80 | auto g = make_guard(inc_i); 81 | EXPECT_EQ(i, 1); 82 | g.dismiss(); 83 | EXPECT_EQ(i, 1); 84 | } 85 | EXPECT_EQ(i, 1); 86 | 87 | { 88 | scoped_guard j(inc_i); 89 | scoped_guard k(inc_i); 90 | EXPECT_EQ(i, 1); 91 | j = std::move(k); // Old j is destroyed. 92 | EXPECT_EQ(i, 2); 93 | j = std::move(j); // Self move is no-op. 94 | EXPECT_EQ(i, 2); 95 | scoped_guard l(std::move(j)); 96 | EXPECT_EQ(i, 2); 97 | } 98 | EXPECT_EQ(i, 3); 99 | } 100 | -------------------------------------------------------------------------------- /testing/serial_executor_test.cc: -------------------------------------------------------------------------------- 1 | // Copyright 2010 Google Inc. All Rights Reserved. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | // Basic test of the serial_executor class. 16 | // Tests that execution works with multiple enqueing threads. 17 | 18 | #include 19 | 20 | #include 21 | 22 | #include 23 | 24 | #include 25 | #include 26 | 27 | #include "called_task.h" 28 | #include "serial_executor.h" 29 | 30 | #include "gmock/gmock.h" 31 | 32 | namespace gcl { 33 | namespace { 34 | 35 | TEST(SerialExecutorTest, SingleExecution) { 36 | Called called(1); 37 | serial_executor exec; 38 | exec.execute(std::bind(&Called::run, &called)); 39 | called.wait(); 40 | 41 | EXPECT_EQ(1, called.count); 42 | } 43 | 44 | TEST(SerialExecutorTest, MultiExecution) { 45 | const int num_exec = 10; 46 | Called called(num_exec); 47 | 48 | serial_executor exec; 49 | // Queue up a number of executions. 50 | for (int i = 0; i < num_exec; ++i) { 51 | exec.execute(std::bind(&Called::run, &called)); 52 | } 53 | called.wait(); 54 | 55 | EXPECT_EQ(num_exec, called.count); 56 | } 57 | 58 | struct LockedTask { 59 | LockedTask(std::mutex* lock) : block_lock(lock) {} 60 | 61 | void run() { 62 | std::unique_lock ul(*block_lock); 63 | ++count; 64 | } 65 | 66 | std::mutex* block_lock; 67 | int count; 68 | }; 69 | 70 | void delete_executor(serial_executor* exec) { 71 | delete exec; 72 | } 73 | 74 | TEST(SerialExecutorTest, ShutdownTest) { 75 | // To test shutting down, we need to create a thread which blocks then kill 76 | // the executor and try to enqueue more stuff, yet make sure that the 77 | // executor thread doesn't actually execute the extra stuff. 78 | std::mutex task_blocker; 79 | task_blocker.lock(); 80 | 81 | LockedTask locked_task(&task_blocker); 82 | 83 | serial_executor* exec = new serial_executor(); 84 | exec->execute(std::bind(&LockedTask::run, &locked_task)); 85 | // Let the executor thread make some progress. 86 | std::this_thread::sleep_for(std::chrono::milliseconds(100)); 87 | 88 | // NOTE: this should deadlock! Need to start a new thread to handle shutdown 89 | // since the executor will block waiting for the running task to join! 90 | std::thread exec_deleter(std::bind(&delete_executor, exec)); 91 | 92 | // Let the deleter make some progress. 93 | std::this_thread::sleep_for(std::chrono::milliseconds(100)); 94 | 95 | // other_task should never execute. 96 | Called other_task(1); 97 | exec->execute(std::bind(&Called::run, &other_task)); 98 | task_blocker.unlock(); 99 | 100 | // Sleep a bit to give the task a chance to run. 101 | std::this_thread::sleep_for(std::chrono::milliseconds(10)); 102 | exec_deleter.join(); 103 | 104 | EXPECT_EQ(0, other_task.count); 105 | } 106 | 107 | struct CountMaker { 108 | CountMaker() : next1(1), next2(2) {} 109 | 110 | void run(serial_executor* executor) { 111 | executor->execute(std::bind(&Called::run, &next2)); 112 | executor->execute(std::bind(&Called::run, &next1)); 113 | executor->execute(std::bind(&Called::run, &next2)); 114 | } 115 | 116 | Called next1; 117 | Called next2; 118 | }; 119 | 120 | TEST(SerialExecutorTest, InlineExecutes) { 121 | CountMaker inlined_counters; 122 | serial_executor exec; 123 | exec.execute(std::bind(&CountMaker::run, &inlined_counters, &exec)); 124 | 125 | inlined_counters.next1.wait(); 126 | inlined_counters.next2.wait(); 127 | 128 | // Check that the spawned executions run as well. 129 | EXPECT_EQ(1, inlined_counters.next1.count); 130 | EXPECT_EQ(2, inlined_counters.next2.count); 131 | } 132 | 133 | } 134 | } // namespace gcl 135 | -------------------------------------------------------------------------------- /testing/simple_thread_pool_test.cc: -------------------------------------------------------------------------------- 1 | // Copyright 2011 Google Inc. All Rights Reserved. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | // Basic test of the simple_thread_pool class. 16 | 17 | #include 18 | 19 | #include 20 | 21 | #include 22 | 23 | #include 24 | 25 | #include "called_task.h" 26 | #include "mutable_thread.h" 27 | #include "simple_thread_pool.h" 28 | 29 | #include "gmock/gmock.h" 30 | 31 | namespace gcl { 32 | namespace { 33 | 34 | TEST(SimpleThreadPoolTest, GetOne) { 35 | simple_thread_pool thread_pool; 36 | mutable_thread* new_thread = thread_pool.try_get_unused_thread(); 37 | EXPECT_FALSE(NULL == new_thread); 38 | 39 | Called called(1); 40 | new_thread->execute(std::bind(&Called::run, &called)); 41 | called.wait(); 42 | EXPECT_EQ(1, called.count); 43 | } 44 | 45 | TEST(SimpleThreadPoolTest, GetAndReturnOne) { 46 | simple_thread_pool thread_pool; 47 | mutable_thread* new_thread = thread_pool.try_get_unused_thread(); 48 | EXPECT_FALSE(NULL == new_thread); 49 | 50 | Called called(1); 51 | new_thread->execute(std::bind(&Called::run, &called)); 52 | called.wait(); 53 | EXPECT_EQ(1, called.count); 54 | 55 | EXPECT_TRUE(thread_pool.donate_thread(new_thread)); 56 | // Thread is now inactive, so it can't be donated again. 57 | EXPECT_FALSE(thread_pool.donate_thread(new_thread)); 58 | } 59 | 60 | TEST(SimpleThreadPoolTest, MultiExecute) { 61 | simple_thread_pool thread_pool; 62 | int num_threads = 10; 63 | 64 | Called called(num_threads); 65 | for (int i = 0; i < num_threads; ++i) { 66 | mutable_thread* new_thread = thread_pool.try_get_unused_thread(); 67 | EXPECT_FALSE(NULL == new_thread); 68 | new_thread->execute(std::bind(&Called::run, &called)); 69 | } 70 | called.wait(); 71 | EXPECT_EQ(10, called.count); 72 | } 73 | 74 | TEST(SimpleThreadPoolTest, OutOfThreads) { 75 | int num_threads = 10; 76 | simple_thread_pool thread_pool(0, num_threads - 1); 77 | 78 | Called called(num_threads); 79 | mutable_thread* a_thread = NULL; 80 | for (int i = 0; i < (num_threads - 1); ++i) { 81 | mutable_thread* new_thread = thread_pool.try_get_unused_thread(); 82 | EXPECT_FALSE(NULL == new_thread); 83 | new_thread->execute(std::bind(&Called::run, &called)); 84 | 85 | if (a_thread == NULL) { 86 | a_thread = new_thread; 87 | } 88 | } 89 | mutable_thread* new_thread = thread_pool.try_get_unused_thread(); 90 | EXPECT_EQ((gcl::mutable_thread*)NULL, new_thread); 91 | 92 | // Now try to release a thread and return it to the unused pile. 93 | while (called.count < (num_threads - 1)) { 94 | // wait 95 | } 96 | 97 | thread_pool.donate_thread(a_thread); 98 | new_thread = thread_pool.try_get_unused_thread(); 99 | EXPECT_FALSE(NULL == new_thread); 100 | new_thread->execute(std::bind(&Called::run, &called)); 101 | 102 | // Should now be able to wait for one last execution 103 | called.wait(); 104 | EXPECT_EQ(num_threads, called.count); 105 | } 106 | 107 | } 108 | } // namespace gcl 109 | -------------------------------------------------------------------------------- /testing/source_test.cc: -------------------------------------------------------------------------------- 1 | // Copyright 2010 Google Inc. All Rights Reserved. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | // This file is a test of the source, using a buffer_queue. 16 | // 17 | // TODO(alasdair): This is a basic sanity check, and needs to be 18 | // expanded. 19 | 20 | #include "source.h" 21 | #include "buffer_queue.h" 22 | 23 | #include "gmock/gmock.h" 24 | 25 | using gcl::source; 26 | using gcl::buffer_queue; 27 | using testing::_; 28 | using testing::Invoke; 29 | using testing::InSequence; 30 | 31 | class SourceTest : public testing::Test { 32 | }; 33 | 34 | TEST_F(SourceTest, Basic) { 35 | buffer_queue queue(5); 36 | queue.push(42); 37 | 38 | source > test_source(&queue); 39 | ASSERT_FALSE(test_source.has_value()); 40 | test_source.wait(); 41 | ASSERT_TRUE(test_source.has_value()); 42 | ASSERT_EQ(42, test_source.get()); 43 | } 44 | -------------------------------------------------------------------------------- /third_party/ThreadSanitizer/Darwin-i386/tsan-self-contained.sh: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alasdairmackintosh/google-concurrency-library/7bd93fff9a985930d0e1e8bf70b75a5805aee634/third_party/ThreadSanitizer/Darwin-i386/tsan-self-contained.sh -------------------------------------------------------------------------------- /third_party/ThreadSanitizer/Linux-x86_64/tsan-self-contained.sh: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alasdairmackintosh/google-concurrency-library/7bd93fff9a985930d0e1e8bf70b75a5805aee634/third_party/ThreadSanitizer/Linux-x86_64/tsan-self-contained.sh -------------------------------------------------------------------------------- /third_party/ThreadSanitizer/README: -------------------------------------------------------------------------------- 1 | This directory contains the binaries of ThreadSanitizer (aka tsan), 2 | a Valgrind-based data race detector. 3 | 4 | For fresh binaries and more details see 5 | http://code.google.com/p/data-race-test/wiki/ThreadSanitizer 6 | 7 | Supported platforms: 8 | * Linux/x86_64, tested only on Ubuntu 8.04, 9 | supports both 32- and 64-bit binaries. 10 | * MacOS X 10.5 (32-bit only) 11 | 12 | Usage example: 13 | srcdir= 14 | objdir= 15 | # Linux: 16 | TSAN="$srcdir/third_party/ThreadSanitizer/Linux-x86_64/tsan-self-contained.sh" 17 | # Mac: 18 | TSAN="$srcdir/third_party/ThreadSanitizer/Darwin-i386/tsan-self-contained.sh --dsymutil=yes" 19 | cd $objdir 20 | # Run in the pure-happens-before (less aggressive) mode. 21 | $TSAN --pure-happens-before ./race_test 22 | # Run in the hybrid (more aggressive) mode. 23 | $TSAN ./race_test 24 | -------------------------------------------------------------------------------- /third_party/googlemock/CHANGES: -------------------------------------------------------------------------------- 1 | Changes for 1.6.0: 2 | 3 | * Compilation is much faster and uses much less memory, especially 4 | when the constructor and destructor of a mock class are moved out of 5 | the class body. 6 | * New matchers: Pointwise(), Each(). 7 | * New actions: ReturnPointee() and ReturnRefOfCopy(). 8 | * CMake support. 9 | * Project files for Visual Studio 2010. 10 | * AllOf() and AnyOf() can handle up-to 10 arguments now. 11 | * Google Mock doctor understands Clang error messages now. 12 | * SetArgPointee<> now accepts string literals. 13 | * gmock_gen.py handles storage specifier macros and template return 14 | types now. 15 | * Compatibility fixes. 16 | * Bug fixes and implementation clean-ups. 17 | * Potentially incompatible changes: disables the harmful 'make install' 18 | command in autotools. 19 | 20 | Potentially breaking changes: 21 | 22 | * The description string for MATCHER*() changes from Python-style 23 | interpolation to an ordinary C++ string expression. 24 | * SetArgumentPointee is deprecated in favor of SetArgPointee. 25 | * Some non-essential project files for Visual Studio 2005 are removed. 26 | 27 | Changes for 1.5.0: 28 | 29 | * New feature: Google Mock can be safely used in multi-threaded tests 30 | on platforms having pthreads. 31 | * New feature: function for printing a value of arbitrary type. 32 | * New feature: function ExplainMatchResult() for easy definition of 33 | composite matchers. 34 | * The new matcher API lets user-defined matchers generate custom 35 | explanations more directly and efficiently. 36 | * Better failure messages all around. 37 | * NotNull() and IsNull() now work with smart pointers. 38 | * Field() and Property() now work when the matcher argument is a pointer 39 | passed by reference. 40 | * Regular expression matchers on all platforms. 41 | * Added GCC 4.0 support for Google Mock Doctor. 42 | * Added gmock_all_test.cc for compiling most Google Mock tests 43 | in a single file. 44 | * Significantly cleaned up compiler warnings. 45 | * Bug fixes, better test coverage, and implementation clean-ups. 46 | 47 | Potentially breaking changes: 48 | 49 | * Custom matchers defined using MatcherInterface or MakePolymorphicMatcher() 50 | need to be updated after upgrading to Google Mock 1.5.0; matchers defined 51 | using MATCHER or MATCHER_P* aren't affected. 52 | * Dropped support for 'make install'. 53 | 54 | Changes for 1.4.0 (we skipped 1.2.* and 1.3.* to match the version of 55 | Google Test): 56 | 57 | * Works in more environments: Symbian and minGW, Visual C++ 7.1. 58 | * Lighter weight: comes with our own implementation of TR1 tuple (no 59 | more dependency on Boost!). 60 | * New feature: --gmock_catch_leaked_mocks for detecting leaked mocks. 61 | * New feature: ACTION_TEMPLATE for defining templatized actions. 62 | * New feature: the .After() clause for specifying expectation order. 63 | * New feature: the .With() clause for for specifying inter-argument 64 | constraints. 65 | * New feature: actions ReturnArg(), ReturnNew(...), and 66 | DeleteArg(). 67 | * New feature: matchers Key(), Pair(), Args<...>(), AllArgs(), IsNull(), 68 | and Contains(). 69 | * New feature: utility class MockFunction, useful for checkpoints, etc. 70 | * New feature: functions Value(x, m) and SafeMatcherCast(m). 71 | * New feature: copying a mock object is rejected at compile time. 72 | * New feature: a script for fusing all Google Mock and Google Test 73 | source files for easy deployment. 74 | * Improved the Google Mock doctor to diagnose more diseases. 75 | * Improved the Google Mock generator script. 76 | * Compatibility fixes for Mac OS X and gcc. 77 | * Bug fixes and implementation clean-ups. 78 | 79 | Changes for 1.1.0: 80 | 81 | * New feature: ability to use Google Mock with any testing framework. 82 | * New feature: macros for easily defining new matchers 83 | * New feature: macros for easily defining new actions. 84 | * New feature: more container matchers. 85 | * New feature: actions for accessing function arguments and throwing 86 | exceptions. 87 | * Improved the Google Mock doctor script for diagnosing compiler errors. 88 | * Bug fixes and implementation clean-ups. 89 | 90 | Changes for 1.0.0: 91 | 92 | * Initial Open Source release of Google Mock 93 | -------------------------------------------------------------------------------- /third_party/googlemock/CONTRIBUTORS: -------------------------------------------------------------------------------- 1 | # This file contains a list of people who've made non-trivial 2 | # contribution to the Google C++ Mocking Framework project. People 3 | # who commit code to the project are encouraged to add their names 4 | # here. Please keep the list sorted by first names. 5 | 6 | Benoit Sigoure 7 | Bogdan Piloca 8 | Chandler Carruth 9 | Dave MacLachlan 10 | David Anderson 11 | Dean Sturtevant 12 | Gene Volovich 13 | Hal Burch 14 | Jeffrey Yasskin 15 | Jim Keller 16 | Joe Walnes 17 | Jon Wray 18 | Keir Mierle 19 | Keith Ray 20 | Kostya Serebryany 21 | Lev Makhlis 22 | Manuel Klimek 23 | Mario Tanev 24 | Mark Paskin 25 | Markus Heule 26 | Matthew Simmons 27 | Mike Bland 28 | Neal Norwitz 29 | Nermin Ozkiranartli 30 | Owen Carlsen 31 | Paneendra Ba 32 | Paul Menage 33 | Piotr Kaminski 34 | Russ Rufer 35 | Sverre Sundsdal 36 | Takeshi Yoshino 37 | Vadim Berman 38 | Vlad Losev 39 | Wolfgang Klier 40 | Zhanyong Wan 41 | -------------------------------------------------------------------------------- /third_party/googlemock/COPYING: -------------------------------------------------------------------------------- 1 | Copyright 2008, Google Inc. 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without 5 | modification, are permitted provided that the following conditions are 6 | met: 7 | 8 | * Redistributions of source code must retain the above copyright 9 | notice, this list of conditions and the following disclaimer. 10 | * Redistributions in binary form must reproduce the above 11 | copyright notice, this list of conditions and the following disclaimer 12 | in the documentation and/or other materials provided with the 13 | distribution. 14 | * Neither the name of Google Inc. nor the names of its 15 | contributors may be used to endorse or promote products derived from 16 | this software without specific prior written permission. 17 | 18 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 21 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 22 | OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 23 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 24 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26 | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | -------------------------------------------------------------------------------- /third_party/googlemock/include/gmock/gmock.h: -------------------------------------------------------------------------------- 1 | // Copyright 2007, Google Inc. 2 | // All rights reserved. 3 | // 4 | // Redistribution and use in source and binary forms, with or without 5 | // modification, are permitted provided that the following conditions are 6 | // met: 7 | // 8 | // * Redistributions of source code must retain the above copyright 9 | // notice, this list of conditions and the following disclaimer. 10 | // * Redistributions in binary form must reproduce the above 11 | // copyright notice, this list of conditions and the following disclaimer 12 | // in the documentation and/or other materials provided with the 13 | // distribution. 14 | // * Neither the name of Google Inc. nor the names of its 15 | // contributors may be used to endorse or promote products derived from 16 | // this software without specific prior written permission. 17 | // 18 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 21 | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 22 | // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 23 | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 24 | // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25 | // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26 | // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | // 30 | // Author: wan@google.com (Zhanyong Wan) 31 | 32 | // Google Mock - a framework for writing C++ mock classes. 33 | // 34 | // This is the main header file a user should include. 35 | 36 | #ifndef GMOCK_INCLUDE_GMOCK_GMOCK_H_ 37 | #define GMOCK_INCLUDE_GMOCK_GMOCK_H_ 38 | 39 | // This file implements the following syntax: 40 | // 41 | // ON_CALL(mock_object.Method(...)) 42 | // .With(...) ? 43 | // .WillByDefault(...); 44 | // 45 | // where With() is optional and WillByDefault() must appear exactly 46 | // once. 47 | // 48 | // EXPECT_CALL(mock_object.Method(...)) 49 | // .With(...) ? 50 | // .Times(...) ? 51 | // .InSequence(...) * 52 | // .WillOnce(...) * 53 | // .WillRepeatedly(...) ? 54 | // .RetiresOnSaturation() ? ; 55 | // 56 | // where all clauses are optional and WillOnce() can be repeated. 57 | 58 | #include "gmock/gmock-actions.h" 59 | #include "gmock/gmock-cardinalities.h" 60 | #include "gmock/gmock-generated-actions.h" 61 | #include "gmock/gmock-generated-function-mockers.h" 62 | #include "gmock/gmock-generated-matchers.h" 63 | #include "gmock/gmock-more-actions.h" 64 | #include "gmock/gmock-generated-nice-strict.h" 65 | #include "gmock/gmock-matchers.h" 66 | #include "gmock/internal/gmock-internal-utils.h" 67 | 68 | namespace testing { 69 | 70 | // Declares Google Mock flags that we want a user to use programmatically. 71 | GMOCK_DECLARE_bool_(catch_leaked_mocks); 72 | GMOCK_DECLARE_string_(verbose); 73 | 74 | // Initializes Google Mock. This must be called before running the 75 | // tests. In particular, it parses the command line for the flags 76 | // that Google Mock recognizes. Whenever a Google Mock flag is seen, 77 | // it is removed from argv, and *argc is decremented. 78 | // 79 | // No value is returned. Instead, the Google Mock flag variables are 80 | // updated. 81 | // 82 | // Since Google Test is needed for Google Mock to work, this function 83 | // also initializes Google Test and parses its flags, if that hasn't 84 | // been done. 85 | void InitGoogleMock(int* argc, char** argv); 86 | 87 | // This overloaded version can be used in Windows programs compiled in 88 | // UNICODE mode. 89 | void InitGoogleMock(int* argc, wchar_t** argv); 90 | 91 | } // namespace testing 92 | 93 | #endif // GMOCK_INCLUDE_GMOCK_GMOCK_H_ 94 | -------------------------------------------------------------------------------- /third_party/googlemock/include/gmock/internal/gmock-port.h: -------------------------------------------------------------------------------- 1 | // Copyright 2008, Google Inc. 2 | // All rights reserved. 3 | // 4 | // Redistribution and use in source and binary forms, with or without 5 | // modification, are permitted provided that the following conditions are 6 | // met: 7 | // 8 | // * Redistributions of source code must retain the above copyright 9 | // notice, this list of conditions and the following disclaimer. 10 | // * Redistributions in binary form must reproduce the above 11 | // copyright notice, this list of conditions and the following disclaimer 12 | // in the documentation and/or other materials provided with the 13 | // distribution. 14 | // * Neither the name of Google Inc. nor the names of its 15 | // contributors may be used to endorse or promote products derived from 16 | // this software without specific prior written permission. 17 | // 18 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 21 | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 22 | // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 23 | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 24 | // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25 | // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26 | // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | // 30 | // Author: vadimb@google.com (Vadim Berman) 31 | // 32 | // Low-level types and utilities for porting Google Mock to various 33 | // platforms. They are subject to change without notice. DO NOT USE 34 | // THEM IN USER CODE. 35 | 36 | #ifndef GMOCK_INCLUDE_GMOCK_INTERNAL_GMOCK_PORT_H_ 37 | #define GMOCK_INCLUDE_GMOCK_INTERNAL_GMOCK_PORT_H_ 38 | 39 | #include 40 | #include 41 | #include 42 | 43 | // Most of the types needed for porting Google Mock are also required 44 | // for Google Test and are defined in gtest-port.h. 45 | #include "gtest/internal/gtest-linked_ptr.h" 46 | #include "gtest/internal/gtest-port.h" 47 | 48 | // To avoid conditional compilation everywhere, we make it 49 | // gmock-port.h's responsibility to #include the header implementing 50 | // tr1/tuple. gmock-port.h does this via gtest-port.h, which is 51 | // guaranteed to pull in the tuple header. 52 | 53 | // For MS Visual C++, check the compiler version. At least VS 2003 is 54 | // required to compile Google Mock. 55 | #if defined(_MSC_VER) && _MSC_VER < 1310 56 | # error "At least Visual C++ 2003 (7.1) is required to compile Google Mock." 57 | #endif 58 | 59 | // Macro for referencing flags. This is public as we want the user to 60 | // use this syntax to reference Google Mock flags. 61 | #define GMOCK_FLAG(name) FLAGS_gmock_##name 62 | 63 | // Macros for declaring flags. 64 | #define GMOCK_DECLARE_bool_(name) extern bool GMOCK_FLAG(name) 65 | #define GMOCK_DECLARE_int32_(name) \ 66 | extern ::testing::internal::Int32 GMOCK_FLAG(name) 67 | #define GMOCK_DECLARE_string_(name) \ 68 | extern ::testing::internal::String GMOCK_FLAG(name) 69 | 70 | // Macros for defining flags. 71 | #define GMOCK_DEFINE_bool_(name, default_val, doc) \ 72 | bool GMOCK_FLAG(name) = (default_val) 73 | #define GMOCK_DEFINE_int32_(name, default_val, doc) \ 74 | ::testing::internal::Int32 GMOCK_FLAG(name) = (default_val) 75 | #define GMOCK_DEFINE_string_(name, default_val, doc) \ 76 | ::testing::internal::String GMOCK_FLAG(name) = (default_val) 77 | 78 | #endif // GMOCK_INCLUDE_GMOCK_INTERNAL_GMOCK_PORT_H_ 79 | -------------------------------------------------------------------------------- /third_party/googlemock/src/gmock-all.cc: -------------------------------------------------------------------------------- 1 | // Copyright 2008, Google Inc. 2 | // All rights reserved. 3 | // 4 | // Redistribution and use in source and binary forms, with or without 5 | // modification, are permitted provided that the following conditions are 6 | // met: 7 | // 8 | // * Redistributions of source code must retain the above copyright 9 | // notice, this list of conditions and the following disclaimer. 10 | // * Redistributions in binary form must reproduce the above 11 | // copyright notice, this list of conditions and the following disclaimer 12 | // in the documentation and/or other materials provided with the 13 | // distribution. 14 | // * Neither the name of Google Inc. nor the names of its 15 | // contributors may be used to endorse or promote products derived from 16 | // this software without specific prior written permission. 17 | // 18 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 21 | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 22 | // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 23 | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 24 | // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25 | // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26 | // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | // 30 | // Author: wan@google.com (Zhanyong Wan) 31 | // 32 | // Google C++ Mocking Framework (Google Mock) 33 | // 34 | // This file #includes all Google Mock implementation .cc files. The 35 | // purpose is to allow a user to build Google Mock by compiling this 36 | // file alone. 37 | 38 | // This line ensures that gmock.h can be compiled on its own, even 39 | // when it's fused. 40 | #include "gmock/gmock.h" 41 | 42 | // The following lines pull in the real gmock *.cc files. 43 | #include "src/gmock-cardinalities.cc" 44 | #include "src/gmock-internal-utils.cc" 45 | #include "src/gmock-matchers.cc" 46 | #include "src/gmock-spec-builders.cc" 47 | #include "src/gmock.cc" 48 | -------------------------------------------------------------------------------- /third_party/googlemock/src/gmock-matchers.cc: -------------------------------------------------------------------------------- 1 | // Copyright 2007, Google Inc. 2 | // All rights reserved. 3 | // 4 | // Redistribution and use in source and binary forms, with or without 5 | // modification, are permitted provided that the following conditions are 6 | // met: 7 | // 8 | // * Redistributions of source code must retain the above copyright 9 | // notice, this list of conditions and the following disclaimer. 10 | // * Redistributions in binary form must reproduce the above 11 | // copyright notice, this list of conditions and the following disclaimer 12 | // in the documentation and/or other materials provided with the 13 | // distribution. 14 | // * Neither the name of Google Inc. nor the names of its 15 | // contributors may be used to endorse or promote products derived from 16 | // this software without specific prior written permission. 17 | // 18 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 21 | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 22 | // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 23 | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 24 | // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25 | // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26 | // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | // 30 | // Author: wan@google.com (Zhanyong Wan) 31 | 32 | // Google Mock - a framework for writing C++ mock classes. 33 | // 34 | // This file implements Matcher, Matcher, and 35 | // utilities for defining matchers. 36 | 37 | #include "gmock/gmock-matchers.h" 38 | #include "gmock/gmock-generated-matchers.h" 39 | 40 | #include 41 | #include 42 | #include 43 | 44 | namespace testing { 45 | 46 | // Constructs a matcher that matches a const string& whose value is 47 | // equal to s. 48 | Matcher::Matcher(const internal::string& s) { 49 | *this = Eq(s); 50 | } 51 | 52 | // Constructs a matcher that matches a const string& whose value is 53 | // equal to s. 54 | Matcher::Matcher(const char* s) { 55 | *this = Eq(internal::string(s)); 56 | } 57 | 58 | // Constructs a matcher that matches a string whose value is equal to s. 59 | Matcher::Matcher(const internal::string& s) { *this = Eq(s); } 60 | 61 | // Constructs a matcher that matches a string whose value is equal to s. 62 | Matcher::Matcher(const char* s) { 63 | *this = Eq(internal::string(s)); 64 | } 65 | 66 | namespace internal { 67 | 68 | // Joins a vector of strings as if they are fields of a tuple; returns 69 | // the joined string. 70 | string JoinAsTuple(const Strings& fields) { 71 | switch (fields.size()) { 72 | case 0: 73 | return ""; 74 | case 1: 75 | return fields[0]; 76 | default: 77 | string result = "(" + fields[0]; 78 | for (size_t i = 1; i < fields.size(); i++) { 79 | result += ", "; 80 | result += fields[i]; 81 | } 82 | result += ")"; 83 | return result; 84 | } 85 | } 86 | 87 | // Returns the description for a matcher defined using the MATCHER*() 88 | // macro where the user-supplied description string is "", if 89 | // 'negation' is false; otherwise returns the description of the 90 | // negation of the matcher. 'param_values' contains a list of strings 91 | // that are the print-out of the matcher's parameters. 92 | string FormatMatcherDescription(bool negation, const char* matcher_name, 93 | const Strings& param_values) { 94 | string result = ConvertIdentifierNameToWords(matcher_name); 95 | if (param_values.size() >= 1) 96 | result += " " + JoinAsTuple(param_values); 97 | return negation ? "not (" + result + ")" : result; 98 | } 99 | 100 | } // namespace internal 101 | } // namespace testing 102 | -------------------------------------------------------------------------------- /third_party/googlemock/src/gmock_main.cc: -------------------------------------------------------------------------------- 1 | // Copyright 2008, Google Inc. 2 | // All rights reserved. 3 | // 4 | // Redistribution and use in source and binary forms, with or without 5 | // modification, are permitted provided that the following conditions are 6 | // met: 7 | // 8 | // * Redistributions of source code must retain the above copyright 9 | // notice, this list of conditions and the following disclaimer. 10 | // * Redistributions in binary form must reproduce the above 11 | // copyright notice, this list of conditions and the following disclaimer 12 | // in the documentation and/or other materials provided with the 13 | // distribution. 14 | // * Neither the name of Google Inc. nor the names of its 15 | // contributors may be used to endorse or promote products derived from 16 | // this software without specific prior written permission. 17 | // 18 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 21 | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 22 | // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 23 | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 24 | // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25 | // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26 | // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | // 30 | // Author: wan@google.com (Zhanyong Wan) 31 | 32 | #include 33 | #include "gmock/gmock.h" 34 | #include "gtest/gtest.h" 35 | 36 | // MS C++ compiler/linker has a bug on Windows (not on Windows CE), which 37 | // causes a link error when _tmain is defined in a static library and UNICODE 38 | // is enabled. For this reason instead of _tmain, main function is used on 39 | // Windows. See the following link to track the current status of this bug: 40 | // http://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=394464 // NOLINT 41 | #if GTEST_OS_WINDOWS_MOBILE 42 | # include // NOLINT 43 | 44 | int _tmain(int argc, TCHAR** argv) { 45 | #else 46 | int main(int argc, char** argv) { 47 | #endif // GTEST_OS_WINDOWS_MOBILE 48 | std::cout << "Running main() from gmock_main.cc\n"; 49 | // Since Google Mock depends on Google Test, InitGoogleMock() is 50 | // also responsible for initializing Google Test. Therefore there's 51 | // no need for calling testing::InitGoogleTest() separately. 52 | testing::InitGoogleMock(&argc, argv); 53 | return RUN_ALL_TESTS(); 54 | } 55 | -------------------------------------------------------------------------------- /third_party/googletest/CONTRIBUTORS: -------------------------------------------------------------------------------- 1 | # This file contains a list of people who've made non-trivial 2 | # contribution to the Google C++ Testing Framework project. People 3 | # who commit code to the project are encouraged to add their names 4 | # here. Please keep the list sorted by first names. 5 | 6 | Ajay Joshi 7 | Balázs Dán 8 | Bharat Mediratta 9 | Chandler Carruth 10 | Chris Prince 11 | Chris Taylor 12 | Dan Egnor 13 | Eric Roman 14 | Hady Zalek 15 | Jeffrey Yasskin 16 | Jói Sigurðsson 17 | Keir Mierle 18 | Keith Ray 19 | Kenton Varda 20 | Manuel Klimek 21 | Markus Heule 22 | Mika Raento 23 | Miklós Fazekas 24 | Pasi Valminen 25 | Patrick Hanna 26 | Patrick Riley 27 | Peter Kaminski 28 | Preston Jackson 29 | Rainer Klaffenboeck 30 | Russ Cox 31 | Russ Rufer 32 | Sean Mcafee 33 | Sigurður Ásgeirsson 34 | Tracy Bialik 35 | Vadim Berman 36 | Vlad Losev 37 | Zhanyong Wan 38 | -------------------------------------------------------------------------------- /third_party/googletest/COPYING: -------------------------------------------------------------------------------- 1 | Copyright 2008, Google Inc. 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without 5 | modification, are permitted provided that the following conditions are 6 | met: 7 | 8 | * Redistributions of source code must retain the above copyright 9 | notice, this list of conditions and the following disclaimer. 10 | * Redistributions in binary form must reproduce the above 11 | copyright notice, this list of conditions and the following disclaimer 12 | in the documentation and/or other materials provided with the 13 | distribution. 14 | * Neither the name of Google Inc. nor the names of its 15 | contributors may be used to endorse or promote products derived from 16 | this software without specific prior written permission. 17 | 18 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 21 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 22 | OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 23 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 24 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26 | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | -------------------------------------------------------------------------------- /third_party/googletest/include/gtest/gtest_prod.h: -------------------------------------------------------------------------------- 1 | // Copyright 2006, Google Inc. 2 | // All rights reserved. 3 | // 4 | // Redistribution and use in source and binary forms, with or without 5 | // modification, are permitted provided that the following conditions are 6 | // met: 7 | // 8 | // * Redistributions of source code must retain the above copyright 9 | // notice, this list of conditions and the following disclaimer. 10 | // * Redistributions in binary form must reproduce the above 11 | // copyright notice, this list of conditions and the following disclaimer 12 | // in the documentation and/or other materials provided with the 13 | // distribution. 14 | // * Neither the name of Google Inc. nor the names of its 15 | // contributors may be used to endorse or promote products derived from 16 | // this software without specific prior written permission. 17 | // 18 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 21 | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 22 | // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 23 | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 24 | // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25 | // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26 | // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | // 30 | // Author: wan@google.com (Zhanyong Wan) 31 | // 32 | // Google C++ Testing Framework definitions useful in production code. 33 | 34 | #ifndef GTEST_INCLUDE_GTEST_GTEST_PROD_H_ 35 | #define GTEST_INCLUDE_GTEST_GTEST_PROD_H_ 36 | 37 | // When you need to test the private or protected members of a class, 38 | // use the FRIEND_TEST macro to declare your tests as friends of the 39 | // class. For example: 40 | // 41 | // class MyClass { 42 | // private: 43 | // void MyMethod(); 44 | // FRIEND_TEST(MyClassTest, MyMethod); 45 | // }; 46 | // 47 | // class MyClassTest : public testing::Test { 48 | // // ... 49 | // }; 50 | // 51 | // TEST_F(MyClassTest, MyMethod) { 52 | // // Can call MyClass::MyMethod() here. 53 | // } 54 | 55 | #define FRIEND_TEST(test_case_name, test_name)\ 56 | friend class test_case_name##_##test_name##_Test 57 | 58 | #endif // GTEST_INCLUDE_GTEST_GTEST_PROD_H_ 59 | -------------------------------------------------------------------------------- /third_party/googletest/src/gtest-all.cc: -------------------------------------------------------------------------------- 1 | // Copyright 2008, Google Inc. 2 | // All rights reserved. 3 | // 4 | // Redistribution and use in source and binary forms, with or without 5 | // modification, are permitted provided that the following conditions are 6 | // met: 7 | // 8 | // * Redistributions of source code must retain the above copyright 9 | // notice, this list of conditions and the following disclaimer. 10 | // * Redistributions in binary form must reproduce the above 11 | // copyright notice, this list of conditions and the following disclaimer 12 | // in the documentation and/or other materials provided with the 13 | // distribution. 14 | // * Neither the name of Google Inc. nor the names of its 15 | // contributors may be used to endorse or promote products derived from 16 | // this software without specific prior written permission. 17 | // 18 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 21 | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 22 | // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 23 | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 24 | // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25 | // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26 | // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | // 30 | // Author: mheule@google.com (Markus Heule) 31 | // 32 | // Google C++ Testing Framework (Google Test) 33 | // 34 | // Sometimes it's desirable to build Google Test by compiling a single file. 35 | // This file serves this purpose. 36 | 37 | // This line ensures that gtest.h can be compiled on its own, even 38 | // when it's fused. 39 | #include "gtest/gtest.h" 40 | 41 | // The following lines pull in the real gtest *.cc files. 42 | #include "src/gtest.cc" 43 | #include "src/gtest-death-test.cc" 44 | #include "src/gtest-filepath.cc" 45 | #include "src/gtest-port.cc" 46 | #include "src/gtest-printers.cc" 47 | #include "src/gtest-test-part.cc" 48 | #include "src/gtest-typed-test.cc" 49 | -------------------------------------------------------------------------------- /third_party/googletest/src/gtest-typed-test.cc: -------------------------------------------------------------------------------- 1 | // Copyright 2008 Google Inc. 2 | // All Rights Reserved. 3 | // 4 | // Redistribution and use in source and binary forms, with or without 5 | // modification, are permitted provided that the following conditions are 6 | // met: 7 | // 8 | // * Redistributions of source code must retain the above copyright 9 | // notice, this list of conditions and the following disclaimer. 10 | // * Redistributions in binary form must reproduce the above 11 | // copyright notice, this list of conditions and the following disclaimer 12 | // in the documentation and/or other materials provided with the 13 | // distribution. 14 | // * Neither the name of Google Inc. nor the names of its 15 | // contributors may be used to endorse or promote products derived from 16 | // this software without specific prior written permission. 17 | // 18 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 21 | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 22 | // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 23 | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 24 | // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25 | // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26 | // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | // 30 | // Author: wan@google.com (Zhanyong Wan) 31 | 32 | #include "gtest/gtest-typed-test.h" 33 | #include "gtest/gtest.h" 34 | 35 | namespace testing { 36 | namespace internal { 37 | 38 | #if GTEST_HAS_TYPED_TEST_P 39 | 40 | // Skips to the first non-space char in str. Returns an empty string if str 41 | // contains only whitespace characters. 42 | static const char* SkipSpaces(const char* str) { 43 | while (IsSpace(*str)) 44 | str++; 45 | return str; 46 | } 47 | 48 | // Verifies that registered_tests match the test names in 49 | // defined_test_names_; returns registered_tests if successful, or 50 | // aborts the program otherwise. 51 | const char* TypedTestCasePState::VerifyRegisteredTestNames( 52 | const char* file, int line, const char* registered_tests) { 53 | typedef ::std::set::const_iterator DefinedTestIter; 54 | registered_ = true; 55 | 56 | // Skip initial whitespace in registered_tests since some 57 | // preprocessors prefix stringizied literals with whitespace. 58 | registered_tests = SkipSpaces(registered_tests); 59 | 60 | Message errors; 61 | ::std::set tests; 62 | for (const char* names = registered_tests; names != NULL; 63 | names = SkipComma(names)) { 64 | const String name = GetPrefixUntilComma(names); 65 | if (tests.count(name) != 0) { 66 | errors << "Test " << name << " is listed more than once.\n"; 67 | continue; 68 | } 69 | 70 | bool found = false; 71 | for (DefinedTestIter it = defined_test_names_.begin(); 72 | it != defined_test_names_.end(); 73 | ++it) { 74 | if (name == *it) { 75 | found = true; 76 | break; 77 | } 78 | } 79 | 80 | if (found) { 81 | tests.insert(name); 82 | } else { 83 | errors << "No test named " << name 84 | << " can be found in this test case.\n"; 85 | } 86 | } 87 | 88 | for (DefinedTestIter it = defined_test_names_.begin(); 89 | it != defined_test_names_.end(); 90 | ++it) { 91 | if (tests.count(*it) == 0) { 92 | errors << "You forgot to list test " << *it << ".\n"; 93 | } 94 | } 95 | 96 | const String& errors_str = errors.GetString(); 97 | if (errors_str != "") { 98 | fprintf(stderr, "%s %s", FormatFileLocation(file, line).c_str(), 99 | errors_str.c_str()); 100 | fflush(stderr); 101 | posix::Abort(); 102 | } 103 | 104 | return registered_tests; 105 | } 106 | 107 | #endif // GTEST_HAS_TYPED_TEST_P 108 | 109 | } // namespace internal 110 | } // namespace testing 111 | -------------------------------------------------------------------------------- /third_party/googletest/src/gtest_main.cc: -------------------------------------------------------------------------------- 1 | // Copyright 2006, Google Inc. 2 | // All rights reserved. 3 | // 4 | // Redistribution and use in source and binary forms, with or without 5 | // modification, are permitted provided that the following conditions are 6 | // met: 7 | // 8 | // * Redistributions of source code must retain the above copyright 9 | // notice, this list of conditions and the following disclaimer. 10 | // * Redistributions in binary form must reproduce the above 11 | // copyright notice, this list of conditions and the following disclaimer 12 | // in the documentation and/or other materials provided with the 13 | // distribution. 14 | // * Neither the name of Google Inc. nor the names of its 15 | // contributors may be used to endorse or promote products derived from 16 | // this software without specific prior written permission. 17 | // 18 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 21 | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 22 | // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 23 | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 24 | // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25 | // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26 | // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | 30 | #include 31 | 32 | #include "gtest/gtest.h" 33 | 34 | GTEST_API_ int main(int argc, char **argv) { 35 | std::cout << "Running main() from gtest_main.cc\n"; 36 | 37 | testing::InitGoogleTest(&argc, argv); 38 | return RUN_ALL_TESTS(); 39 | } 40 | -------------------------------------------------------------------------------- /util/exetest.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | rm -f $1.pass $1.fail 3 | ./$1.exe >/tmp/$1.run 2>&1 4 | if test $? -eq 0 5 | then 6 | mv /tmp/$1.run $1.pass 7 | exit 0 8 | else 9 | cat /tmp/$1.run 10 | mv /tmp/$1.run $1.fail 11 | exit 1 12 | fi 13 | -------------------------------------------------------------------------------- /util/makejobs.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # Copyright 2011 Google Inc. All Rights Reserved. 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | 17 | if test -r /proc/cpuinfo 18 | then 19 | # Linux 20 | echo '-j' `grep -c processor /proc/cpuinfo` 21 | elif test -x /usr/sbin/system_profiler 22 | then 23 | # Mac OS X 24 | # from http://tech.serbinn.net/2010/ 25 | # detect-number-of-cpu-cores-in-shell-script-mac-os-x-snow-leopard/ 26 | /usr/sbin/system_profiler -detailLevel full SPHardwareDataType | 27 | awk '/Total Number Of Cores/ {printf("-j %d\n", $5)};' 28 | #else unknown 29 | # assume one job, so no -j flag 30 | fi 31 | -------------------------------------------------------------------------------- /wiki/CurrentTaskList.wiki: -------------------------------------------------------------------------------- 1 | #summary Assigned Tasks. 2 | 3 | = Introduction = 4 | 5 | This is mainly a tracking document to keep a list of the outstanding tasks and whom they are assigned to with expected completion times. 6 | 7 | = Task List = 8 | 9 | ||Task||Owner||Expected Date||Comments|| 10 | ||Dynamic Thread Pool||ccmysen||2010-12-17||Somewhat stalled due to pipeline discussion|| 11 | ||Pipeline Design||.||.||Need to spec out tasks for this|| 12 | ||Pipeline Approach to Sources||adam.berkan||.||.|| 13 | ||Pipeline Approach to Graphics||alasdair.mackintosh||.||.|| 14 | ||Pipeline Approach to MapReduce||ccmysen||.||.|| 15 | ||Pipeline Approach to Compilers||lawrence.crowl||.||.|| 16 | ||Java/Scala Research into new Parallel Support||ccmysen||.||.|| 17 | ||.||lawrence.crowl||.||.|| 18 | ||Source & Sync Refcounting||aladsair.mackintosh||.||Stalled due to pipeline discussion|| 19 | ||Alarm Service||adam.berkan||.||.|| 20 | ||Concurrent Queue||flubbyl||.||.|| 21 | ||Concurrent Skip List||flubbyl||.||.|| 22 | ||Documentation of the Existing Classes||alasdair.mackintosh,ccmysen||.||.|| -------------------------------------------------------------------------------- /wiki/GettingStarted.wiki: -------------------------------------------------------------------------------- 1 | #summary How to get started using or contributing to GCL 2 | 3 | == Dependencies == 4 | * svn This should be available on most machines/distributions 5 | * The standard make utility 6 | * A C++ compiler, ideally one like [http://gcc.gnu.org/gcc-4.6/cxx0x_status.html gcc-4.6] that can be configured to conform to either the C++98 standard or the C++11 standard. 7 | * [http://codereview.appspot.com/static/upload.py Reitveld's upload.py]: For getting patches code reviewed. Put this in your path. 8 | 9 | == How to build == 10 | 11 | You can build using the supplied `Makefile`. 12 | 13 | {{{ 14 | $ mkdir gcl-whatever 15 | $ cd gcl-whatever 16 | $ svn checkout https://google-concurrency-library.googlecode.com/svn/ google-concurrency-library 17 | # build libraries 18 | $ make 19 | # run tests 20 | $ make test 21 | }}} 22 | 23 | 24 | 25 | == How to contribute == 26 | 27 | === Overview === 28 | Before committing changes to the central repository, you will need to have them reviewed. To do this, use http://codereview.appspot.com/use_uploadpy to 29 | upload your patch to Reitveld so someone can review it. Running 30 | `upload.py` with no arguments will create a new patch from your local 31 | uncommitted changes. If you've already uploaded a patch, say to http://codereview.appspot.com/164050, then run `upload.py -i 164050` to update it. 32 | 33 | 34 | === Getting changes approved === 35 | When using upload.py with no arguments, it won't 36 | send email to let anyone know there's a review waiting for them. Go to 37 | the codereview.appspot.com URL it gives you, click "Edit Issue" to 38 | fill in the description and reviewers (make sure this includes 39 | `google-concurrency-library@googlegroups.com` to archive all reviews), 40 | and then click the "Publish+Mail Comments ('m')" link to send the 41 | review request. The first mail will automatically include the change's 42 | description. 43 | 44 | If you're not a committer, all you have to do is keep uploading new versions until the reviewers are happy, and then they'll commit it for you. 45 | 46 | If you are a committer, once your change is reviewed, run `svn commit` to commit your changes to the main repository. If prompted for a password, you will need your Google Code password from http://code.google.com/hosting/settings. 47 | === Editing wiki === 48 | If you don't want to edit the wiki from the browser, do this: 49 | * Checkout the wiki files from the repository. `svn checkout https://google-concurrency-library.googlecode.com/svn/wiki` (This will create a new directory with all wiki pages. Do it once) 50 | * Edit the wiki page using your favourite editor. 51 | * Commit the changes as described above. 52 | * `svn commit -m "Edited wiki" && hg push` 53 | -------------------------------------------------------------------------------- /wiki/RaceDetectionTools.wiki: -------------------------------------------------------------------------------- 1 | #summary Testing "Google Concurrency Library for C++" with data race detectors 2 | 3 | 4 | 5 | = Introduction = 6 | We want to simplify race detection for the programs that use "Google Concurrency Library for C++" and to make sure the library itself has no races. 7 | 8 | = Tools = 9 | 10 | Currently supported tools: 11 | * [http://code.google.com/p/data-race-test/wiki/ThreadSanitizer ThreadSanitizer] 12 | 13 | Tools we want to support: 14 | * [http://valgrind.org/docs/manual/hg-manual.html Helgrind] 15 | * [http://valgrind.org/docs/manual/drd-manual.html DRD] 16 | * [http://software.intel.com/en-us/intel-parallel-inspector Intel Parallel Inspector] 17 | * More? 18 | 19 | = !ThreadSanitizer = 20 | Google Concurrency Library comes with pre-compiled binaries of 21 | [http://code.google.com/p/data-race-test/wiki/ThreadSanitizer ThreadSanitizer] 22 | for the following platforms: 23 | * Linux/x86_64 24 | * MacOS X 10.5 25 | 26 | == Example == 27 | You can run !ThreadSanitizer on `race_test` or any other test: 28 | {{{ 29 | srcdir= 30 | objdir= 31 | # Linux: 32 | TSAN="$srcdir/third_party/ThreadSanitizer/Linux-x86_64/tsan-self-contained.sh" 33 | # Mac: 34 | TSAN="$srcdir/third_party/ThreadSanitizer/Darwin-i386/tsan-self-contained.sh --dsymutil=yes" 35 | cd $objdir 36 | # Run in the pure-happens-before (less aggressive) mode. 37 | $TSAN --pure-happens-before ./race_test 38 | # Run in the hybrid (more aggressive) mode. 39 | $TSAN ./race_test 40 | }}} 41 | 42 | The two major modes of !ThreadSanitizer are: 43 | * Hybrid (default): finds more races, but may report false positives. 44 | * Pure Happens-before (add `--pure-happens-before` flag): finds less races; less predictable; will report false positives *only* if the program has custom lock-free synchronization. 45 | 46 | 47 | Example of output (from `testing/race_test.cc`, `ThreadTest.SimpleDataRaceTest`): 48 | {{{ 49 | ==10430== WARNING: Possible data race during read of size 4 at 0x7FF000144: {{{ 50 | ==10430== T2 (locks held: {}): 51 | ==10430== #0 IncrementArg1(int*) testing/race_test.cc:16 52 | ==10430== #1 std::tr1::_Bind::operator()() /usr/include/c++/4.2/tr1/bind_iterate.h:45 53 | ==10430== #2 std::tr1::_Function_handler<...>::_M_invoke(std::tr1::_Any_data const&) /usr/include/c++/4.2/tr1/functional_iterate.h:502 54 | ==10430== #3 std::tr1::function::operator()() const /usr/include/c++/4.2/tr1/functional_iterate.h:865 55 | ==10430== #4 (anonymous namespace)::thread_bootstrap(void*) src/thread.cc:20 56 | ==10430== #5 ThreadSanitizerStartThread /tmp/tsan/valgrind/tsan/ts_valgrind_intercepts.c:504 57 | ==10430== Concurrent write(s) happened at (OR AFTER) these points: 58 | ==10430== T1 (locks held: {}): 59 | ==10430== #0 IncrementArg1(int*) testing/race_test.cc:15 60 | ==10430== #1 std::tr1::_Bind::operator()() /usr/include/c++/4.2/tr1/bind_iterate.h:45 61 | ==10430== #2 std::tr1::_Function_handler<...>::_M_invoke(std::tr1::_Any_data const&) /usr/include/c++/4.2/tr1/functional_iterate.h:502 62 | ==10430== #3 std::tr1::function::operator()() const /usr/include/c++/4.2/tr1/functional_iterate.h:865 63 | ==10430== #4 (anonymous namespace)::thread_bootstrap(void*) src/thread.cc:20 64 | ==10430== #5 ThreadSanitizerStartThread /tmp/tsan/valgrind/tsan/ts_valgrind_intercepts.c:504 65 | ==10430== Location 0x7FF000144 is 3764 bytes inside T0's stack [0x7FE800FF8,0x7FF000FF8] 66 | ==10430== }}} 67 | }}} 68 | 69 | 70 | For more details and examples refer to [http://code.google.com/p/data-race-test/wiki/ThreadSanitizer ThreadSanitizer] home page. 71 | 72 | = Helgrind, DRD = 73 | You may try *Helgrind* or *DRD* which come as a part of [http://www.valgrind.org Valgrind] distribution. 74 | 75 | Example: 76 | {{{ 77 | valgrind --tool=helgrind ./race_test 78 | valgrind --tool=drd ./race_test 79 | }}} 80 | 81 | Helgrind and DRD from Valgrind 3.5 are somewhat similar 82 | to !ThreadSanitizer in pure happens-before mode, but have different amount of false negatives/positives and different details in output. 83 | 84 | = Dynamic Annotations = 85 | [http://code.google.com/p/data-race-test/wiki/DynamicAnnotations Dynamic Annotations] 86 | allow to explain custom synchronization and expected/benign race to race detectors. 87 | 88 | TODO: add support of Dynamic Annotations to "Google Concurrency Library for C++" 89 | -------------------------------------------------------------------------------- /wiki/SubmittedProposals.wiki: -------------------------------------------------------------------------------- 1 | #summary List of Proposals that have been sent to the C++ Committee. 2 | 3 | Current WG21 proposals: 4 | 5 | [http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3533.html N3533 C++ Concurrent Queues] 6 | 7 | [http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3534.html N3534 C++ Pipelines] 8 | 9 | [http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3535.html N3535 C++ Stream Mutexes] 10 | 11 | [http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3563.pdf N3563 C++ Mapreduce] 12 | 13 | [http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3600.html N3600 C++ Latches and Barriers] 14 | 15 | 16 | Earlier proposals: 17 | 18 | [http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2012/n3353.html] 19 | 20 | [http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2012/n3354.html] 21 | 22 | [http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2012/n3355.html] 23 | 24 | [http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2012/n3356.html] 25 | 26 | [http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2012/n3446.pdf] --------------------------------------------------------------------------------