Index: base/shared_memory_unittest.cc |
=================================================================== |
--- base/shared_memory_unittest.cc (revision 2038) |
+++ base/shared_memory_unittest.cc (working copy) |
@@ -2,78 +2,108 @@ |
// 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)); |
+ 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(); |
} |
- 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(); |
- } |
- memory2.Close(); |
- return 0; |
-} |
+ private: |
+ int id_; |
+ |
+ DISALLOW_COPY_AND_ASSIGN(MultipleLockThread); |
+}; |
+#endif |
+ |
} // namespace |
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 @@ |
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 |