Coverage Report

Created: 2018-09-25 14:53

/src/mozilla-central/xpcom/tests/gtest/TestRWLock.cpp
Line
Count
Source (jump to first uncovered line)
1
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
3
/* This Source Code Form is subject to the terms of the Mozilla Public
4
 * License, v. 2.0. If a copy of the MPL was not distributed with this
5
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6
7
#include "nsThreadUtils.h"
8
#include "mozilla/Atomics.h"
9
#include "mozilla/RWLock.h"
10
#include "gtest/gtest.h"
11
12
using mozilla::RWLock;
13
14
static const size_t sNumThreads = 4;
15
static const size_t sOuterIterations = 100;
16
static const size_t sInnerIterations = 100;
17
static const size_t sWriteLockIteration = 10;
18
19
// Based on example code from _Programming with POSIX Threads_.  Not an actual
20
// test of correctness, but more of a "does this work at all" sort of test.
21
22
class RWLockRunnable : public mozilla::Runnable {
23
public:
24
  RWLockRunnable(RWLock* aRWLock, mozilla::Atomic<size_t>* aSharedData)
25
    : mozilla::Runnable("RWLockRunnable")
26
    , mRWLock(aRWLock)
27
    , mSharedData(aSharedData)
28
0
  {}
29
30
  NS_DECL_NSIRUNNABLE
31
32
private:
33
  ~RWLockRunnable() = default;
34
35
  RWLock* mRWLock;
36
  mozilla::Atomic<size_t>* mSharedData;
37
};
38
39
NS_IMETHODIMP
40
RWLockRunnable::Run()
41
0
{
42
0
  for (size_t i = 0; i < sOuterIterations; ++i) {
43
0
    if (i % sWriteLockIteration == 0) {
44
0
      mozilla::AutoWriteLock lock(*mRWLock);
45
0
46
0
      ++(*mSharedData);
47
0
    } else {
48
0
      mozilla::AutoReadLock lock(*mRWLock);
49
0
50
0
      // Loop and try to force other threads to run, but check that our
51
0
      // shared data isn't being modified by them.
52
0
      size_t initialValue = *mSharedData;
53
0
      for (size_t j = 0; j < sInnerIterations; ++j) {
54
0
        EXPECT_EQ(initialValue, *mSharedData);
55
0
56
0
        // This is a magic yield call.
57
0
        PR_Sleep(PR_INTERVAL_NO_WAIT);
58
0
      }
59
0
    }
60
0
  }
61
0
62
0
  return NS_OK;
63
0
}
64
65
TEST(RWLock, SmokeTest)
66
0
{
67
0
  nsCOMPtr<nsIThread> threads[sNumThreads];
68
0
  RWLock rwlock("test lock");
69
0
  mozilla::Atomic<size_t> data(0);
70
0
71
0
  for (size_t i = 0; i < sNumThreads; ++i) {
72
0
    nsCOMPtr<nsIRunnable> event = new RWLockRunnable(&rwlock, &data);
73
0
    NS_NewNamedThread("RWLockTester", getter_AddRefs(threads[i]), event);
74
0
  }
75
0
76
0
  // Wait for all the threads to finish.
77
0
  for (size_t i = 0; i < sNumThreads; ++i) {
78
0
    nsresult rv = threads[i]->Shutdown();
79
0
    EXPECT_TRUE(NS_SUCCEEDED(rv));
80
0
  }
81
0
82
0
  EXPECT_EQ(data, (sOuterIterations / sWriteLockIteration) * sNumThreads);
83
0
}