summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--base/base.xcodeproj/project.pbxproj4
-rw-r--r--base/shared_memory_unittest.cc194
2 files changed, 113 insertions, 85 deletions
diff --git a/base/base.xcodeproj/project.pbxproj b/base/base.xcodeproj/project.pbxproj
index fe90c36..d0b6ff9 100644
--- a/base/base.xcodeproj/project.pbxproj
+++ b/base/base.xcodeproj/project.pbxproj
@@ -152,6 +152,7 @@
ABF4B9BE0DC2BD1500A6E319 /* sha512.cc in Sources */ = {isa = PBXBuildFile; fileRef = 825403700D92D2840006B936 /* sha512.cc */; };
ABF4B9C30DC2BD6C00A6E319 /* values.cc in Sources */ = {isa = PBXBuildFile; fileRef = 825403880D92D2CF0006B936 /* values.cc */; };
ABFBD3E60DC793C600E164CB /* md5.cc in Sources */ = {isa = PBXBuildFile; fileRef = 825403290D92D2090006B936 /* md5.cc */; };
+ BA5CC5840E788093004EDD45 /* shared_memory_unittest.cc in Sources */ = {isa = PBXBuildFile; fileRef = BA5CC5830E788093004EDD45 /* shared_memory_unittest.cc */; };
BA739A020E5E3242009842A7 /* tracked_objects_unittest.cc in Sources */ = {isa = PBXBuildFile; fileRef = BA739A000E5E3242009842A7 /* tracked_objects_unittest.cc */; };
BA739A030E5E3242009842A7 /* timer_unittest.cc in Sources */ = {isa = PBXBuildFile; fileRef = BA739A010E5E3242009842A7 /* timer_unittest.cc */; };
BA73AA330E5F614B00A20026 /* condition_variable_unittest.cc in Sources */ = {isa = PBXBuildFile; fileRef = BA73AA320E5F614B00A20026 /* condition_variable_unittest.cc */; };
@@ -567,6 +568,7 @@
ABF4B98E0DC2BA6900A6E319 /* base_paths_mac.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = base_paths_mac.mm; sourceTree = "<group>"; };
ABF4B99D0DC2BB6000A6E319 /* clipboard_mac.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = clipboard_mac.mm; sourceTree = "<group>"; };
ABF4B9B40DC2BC9F00A6E319 /* path_service.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = path_service.cc; sourceTree = "<group>"; };
+ BA5CC5830E788093004EDD45 /* shared_memory_unittest.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = shared_memory_unittest.cc; sourceTree = "<group>"; };
BA739A000E5E3242009842A7 /* tracked_objects_unittest.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = tracked_objects_unittest.cc; sourceTree = "<group>"; };
BA739A010E5E3242009842A7 /* timer_unittest.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = timer_unittest.cc; sourceTree = "<group>"; };
BA73AA320E5F614B00A20026 /* condition_variable_unittest.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = condition_variable_unittest.cc; sourceTree = "<group>"; };
@@ -880,6 +882,7 @@
825403740D92D2CF0006B936 /* shared_event.h */,
825403760D92D2CF0006B936 /* shared_memory.h */,
824653730DC12D0E007C2BAA /* shared_memory_posix.cc */,
+ BA5CC5830E788093004EDD45 /* shared_memory_unittest.cc */,
7BAE30E20E6D939800C3F750 /* simple_thread.cc */,
7BAE30E30E6D939800C3F750 /* simple_thread.h */,
7BAE30E40E6D939800C3F750 /* simple_thread_unittest.cc */,
@@ -1342,6 +1345,7 @@
7B78D39A0E54FE0100609465 /* run_all_unittests.cc in Sources */,
7BD8F4D50E65B55000034DE9 /* scoped_ptr_unittest.cc in Sources */,
7B78D39B0E54FE0100609465 /* sha2_unittest.cc in Sources */,
+ BA5CC5840E788093004EDD45 /* shared_memory_unittest.cc in Sources */,
7BAE30E60E6D939F00C3F750 /* simple_thread_unittest.cc in Sources */,
7B78D39C0E54FE0100609465 /* singleton_unittest.cc in Sources */,
7B78D39D0E54FE0100609465 /* stack_container_unittest.cc in Sources */,
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