diff options
Diffstat (limited to 'base/shared_memory_unittest.cc')
-rw-r--r-- | base/shared_memory_unittest.cc | 194 |
1 files changed, 109 insertions, 85 deletions
diff --git a/base/shared_memory_unittest.cc b/base/shared_memory_unittest.cc index 274c480..89df135 100644 --- a/base/shared_memory_unittest.cc +++ b/base/shared_memory_unittest.cc @@ -2,69 +2,99 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include <process.h> // _beginthreadex +#include "base/basictypes.h" +#include "base/platform_thread.h" #include "base/shared_memory.h" #include "testing/gtest/include/gtest/gtest.h" +static const int kNumThreads = 5; namespace { class SharedMemoryTest : public testing::Test { }; -unsigned __stdcall MultipleThreadMain(void* param) { - // Each thread will open the shared memory. Each thread will take - // a different 4 byte int pointer, and keep changing it, with some - // small pauses in between. Verify that each thread's value in the - // shared memory is always correct. - const int kDataSize = 1024; - std::wstring test_name = L"SharedMemoryOpenThreadTest"; - int16 id = reinterpret_cast<int16>(param); - SharedMemory memory; - bool rv = memory.Create(test_name, false, true, kDataSize); - EXPECT_TRUE(rv); - rv = memory.Map(kDataSize); - EXPECT_TRUE(rv); - int *ptr = static_cast<int*>(memory.memory()) + id; - EXPECT_EQ(*ptr, 0); - for (int idx = 0; idx < 100; idx++) { - *ptr = idx; - Sleep(1); // short wait - EXPECT_EQ(*ptr, idx); +// Each thread will open the shared memory. Each thread will take a different 4 +// byte int pointer, and keep changing it, with some small pauses in between. +// Verify that each thread's value in the shared memory is always correct. +class MultipleThreadMain : public PlatformThread::Delegate { + public: + explicit MultipleThreadMain(int16 id) : id_(id) {} + ~MultipleThreadMain() {} + + // PlatformThread::Delegate interface. + void ThreadMain() { + const int kDataSize = 1024; + std::wstring test_name = L"SharedMemoryOpenThreadTest"; + SharedMemory memory; + bool rv = memory.Create(test_name, false, true, kDataSize); + EXPECT_TRUE(rv); + rv = memory.Map(kDataSize); + EXPECT_TRUE(rv); + int *ptr = static_cast<int*>(memory.memory()) + id_; + EXPECT_EQ(*ptr, 0); + + for (int idx = 0; idx < 100; idx++) { + *ptr = idx; + PlatformThread::Sleep(1); // Short wait. + EXPECT_EQ(*ptr, idx); + } + + memory.Close(); } - memory.Close(); - return 0; -} -unsigned __stdcall MultipleLockThread(void* param) { - // Each thread will open the shared memory. Each thread will take - // the memory, and keep changing it while trying to lock it, with some - // small pauses in between. Verify that each thread's value in the - // shared memory is always correct. - const int kDataSize = sizeof(int); - int id = static_cast<int>(reinterpret_cast<INT_PTR>(param)); - SharedMemoryHandle handle = NULL; - { - SharedMemory memory1; - EXPECT_TRUE(memory1.Create(L"SharedMemoryMultipleLockThreadTest", false, true, - kDataSize)); - EXPECT_TRUE(memory1.ShareToProcess(GetCurrentProcess(), &handle)); - } - SharedMemory memory2(handle, false); - EXPECT_TRUE(memory2.Map(kDataSize)); - volatile int* const ptr = static_cast<int*>(memory2.memory()); - for (int idx = 0; idx < 20; idx++) { - memory2.Lock(); - int i = (id << 16) + idx; - *ptr = i; - // short wait - Sleep(1); - EXPECT_EQ(*ptr, i); - memory2.Unlock(); + private: + int16 id_; + + DISALLOW_COPY_AND_ASSIGN(MultipleThreadMain); +}; + +#if defined(OS_WIN) +// Each thread will open the shared memory. Each thread will take the memory, +// and keep changing it while trying to lock it, with some small pauses in +// between. Verify that each thread's value in the shared memory is always +// correct. +class MultipleLockThread : public PlatformThread::Delegate { + public: + explicit MultipleLockThread(int id) : id_(id) {} + ~MultipleLockThread() {} + + // PlatformThread::Delegate interface. + void ThreadMain() { + const int kDataSize = sizeof(int); + SharedMemoryHandle handle = NULL; + { + SharedMemory memory1; + EXPECT_TRUE(memory1.Create(L"SharedMemoryMultipleLockThreadTest", + false, true, kDataSize)); + EXPECT_TRUE(memory1.ShareToProcess(GetCurrentProcess(), &handle)); + // TODO(paulg): Implement this once we have a posix version of + // SharedMemory::ShareToProcess. + EXPECT_TRUE(true); + } + + SharedMemory memory2(handle, false); + EXPECT_TRUE(memory2.Map(kDataSize)); + volatile int* const ptr = static_cast<int*>(memory2.memory()); + + for (int idx = 0; idx < 20; idx++) { + memory2.Lock(); + int i = (id_ << 16) + idx; + *ptr = i; + PlatformThread::Sleep(1); // Short wait. + EXPECT_EQ(*ptr, i); + memory2.Unlock(); + } + + memory2.Close(); } - memory2.Close(); - return 0; -} + + private: + int id_; + + DISALLOW_COPY_AND_ASSIGN(MultipleLockThread); +}; +#endif } // namespace @@ -72,8 +102,8 @@ TEST(SharedMemoryTest, OpenClose) { const int kDataSize = 1024; std::wstring test_name = L"SharedMemoryOpenCloseTest"; - // Open two handles to a memory segment, confirm that they - // are mapped separately yet point to the same space. + // Open two handles to a memory segment, confirm that they are mapped + // separately yet point to the same space. SharedMemory memory1; bool rv = memory1.Open(test_name, false); EXPECT_FALSE(rv); @@ -86,71 +116,65 @@ TEST(SharedMemoryTest, OpenClose) { EXPECT_TRUE(rv); rv = memory2.Map(kDataSize); EXPECT_TRUE(rv); - EXPECT_NE(memory1.memory(), memory2.memory()); // compare the pointers + EXPECT_NE(memory1.memory(), memory2.memory()); // Compare the pointers. // Write data to the first memory segment, verify contents of second. memset(memory1.memory(), '1', kDataSize); EXPECT_EQ(memcmp(memory1.memory(), memory2.memory(), kDataSize), 0); - // Close the first memory segment, and verify the - // second still has the right data. + // Close the first memory segment, and verify the second has the right data. memory1.Close(); char *start_ptr = static_cast<char *>(memory2.memory()); char *end_ptr = start_ptr + kDataSize; for (char* ptr = start_ptr; ptr < end_ptr; ptr++) EXPECT_EQ(*ptr, '1'); - // Close the second memory segment + // Close the second memory segment. memory2.Close(); } - +#if defined(OS_WIN) +// Create a set of 5 threads to each open a shared memory segment and write to +// it. Verify that they are always reading/writing consistent data. TEST(SharedMemoryTest, MultipleThreads) { - // Create a set of 5 threads to each open a shared memory segment - // and write to it. Verify that they are always reading/writing - // consistent data. - const int kNumThreads = 5; - HANDLE threads[kNumThreads]; + PlatformThreadHandle thread_handles[kNumThreads]; + MultipleThreadMain* thread_delegates[kNumThreads]; // Spawn the threads. for (int16 index = 0; index < kNumThreads; index++) { - void *argument = reinterpret_cast<void*>(index); - unsigned thread_id; - threads[index] = reinterpret_cast<HANDLE>( - _beginthreadex(NULL, 0, MultipleThreadMain, argument, 0, &thread_id)); - EXPECT_NE(threads[index], static_cast<HANDLE>(NULL)); + PlatformThreadHandle pth; + thread_delegates[index] = new MultipleThreadMain(index); + EXPECT_TRUE(PlatformThread::Create(0, thread_delegates[index], &pth)); + thread_handles[index] = pth; } // Wait for the threads to finish. for (int index = 0; index < kNumThreads; index++) { - DWORD rv = WaitForSingleObject(threads[index], 60*1000); - EXPECT_EQ(rv, WAIT_OBJECT_0); // verify all threads finished - CloseHandle(threads[index]); + PlatformThread::Join(thread_handles[index]); + delete thread_delegates[index]; } } - +// Create a set of threads to each open a shared memory segment and write to it +// with the lock held. Verify that they are always reading/writing consistent +// data. TEST(SharedMemoryTest, Lock) { - // Create a set of threads to each open a shared memory segment and write to - // it with the lock held. Verify that they are always reading/writing - // consistent data. - const int kNumThreads = 5; - HANDLE threads[kNumThreads]; + PlatformThreadHandle thread_handles[kNumThreads]; + MultipleLockThread* thread_delegates[kNumThreads]; // Spawn the threads. for (int index = 0; index < kNumThreads; ++index) { - void *argument = reinterpret_cast<void*>(static_cast<INT_PTR>(index)); - threads[index] = reinterpret_cast<HANDLE>( - _beginthreadex(NULL, 0, &MultipleLockThread, argument, 0, NULL)); - EXPECT_NE(threads[index], static_cast<HANDLE>(NULL)); + PlatformThreadHandle pth; + thread_delegates[index] = new MultipleLockThread(index); + EXPECT_TRUE(PlatformThread::Create(0, thread_delegates[index], &pth)); + thread_handles[index] = pth; } // Wait for the threads to finish. for (int index = 0; index < kNumThreads; ++index) { - DWORD rv = WaitForSingleObject(threads[index], 60*1000); - EXPECT_EQ(rv, WAIT_OBJECT_0); // verify all threads finished - CloseHandle(threads[index]); + PlatformThread::Join(thread_handles[index]); + delete thread_delegates[index]; } } - +#endif |