/[svn]/linuxsampler/trunk/src/testcases/ConditionTest.cpp
ViewVC logotype

Contents of /linuxsampler/trunk/src/testcases/ConditionTest.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 3766 - (show annotations) (download)
Mon Apr 6 12:41:49 2020 UTC (4 years ago) by schoenebeck
File size: 3707 byte(s)
Fixed deadlocks (e.g. when restarting engines).

* Individual thread implementations (e.g. disk thread, etc.):
  Disable thread cancellation on critical sections, e.g. when holding
  mutex locks, to prevent deadlocks if thread is stopped and/or
  restarted.

* Added TestCancel() calls to thread implementations if missing.

* No need to wrap Thread::TestCancel() calls into
  CONFIG_PTHREAD_TESTCANCEL macro conditions (since TestCancel() is
  already a stub on systems which don't have pthread_testcancel()
  available).

* If compiled for debugging: give each thread a human readable name
  to simplify debugging of multi-threading issues.

* DiskThreadBase: TestCancel() and pthread_testcancel() calls are
  per-se redundant, so only call TestCancel().

* Added missing override keywords to silent compiler warnings.

* Bumped version (2.1.1.svn54).

1 #include "ConditionTest.h"
2
3 #include <iostream>
4
5 CPPUNIT_TEST_SUITE_REGISTRATION(ConditionTest);
6
7 using namespace std;
8
9
10 // ConditionChecker
11
12 ConditionTest::ConditionChecker::ConditionChecker(bool waitFor) : Thread(false, false, 0, -4) {
13 resource = 0;
14 this->waitFor = waitFor;
15 }
16
17 int ConditionTest::ConditionChecker::Main() {
18 condition.WaitAndUnlockIf(!waitFor);
19 resource++;
20 return 0;
21 }
22
23
24 // ConditionSetter
25
26 ConditionTest::ConditionSetter::ConditionSetter(Condition* condition, bool toSet) : Thread(false, false, 0, -4) {
27 resource = 0;
28 this->toSet = toSet;
29 this->condition = condition;
30 }
31
32 int ConditionTest::ConditionSetter::Main() {
33 condition->Set(toSet);
34 resource++;
35 return 0;
36 }
37
38
39 // ConditionCheckerLocking
40
41 Condition ConditionTest::ConditionCheckerLocking::staticcondition; // we sheare the same Condition object between all instances of ConditionCheckerLocking
42
43 ConditionTest::ConditionCheckerLocking::ConditionCheckerLocking(bool waitFor) : ConditionChecker(waitFor) {
44 doUnlock = false;
45 }
46
47 int ConditionTest::ConditionCheckerLocking::Main() {
48 staticcondition.WaitIf(!waitFor);
49 resource++;
50 while (!doUnlock) {
51 usleep(1000); // sleep until ordered to unlock the condition again
52 TestCancel();
53 }
54 staticcondition.Unlock();
55 return 0;
56 }
57
58
59 // ConditionTest
60
61 void ConditionTest::printTestSuiteName() {
62 cout << "\b \nRunning Condition Tests: " << flush;
63 }
64
65 void ConditionTest::setUp() {
66 }
67
68 void ConditionTest::tearDown() {
69 }
70
71
72 // Check if Condition class doesn't block if desired condition is already reached
73 void ConditionTest::testDoesntBlockOnDesiredCondtion() {
74 ConditionChecker t(false);
75 t.SignalStartThread();
76 usleep(200000); // wait 200ms
77 CPPUNIT_ASSERT(t.resource == 1);
78 }
79
80 // Check if Condition class blocks if desired condition is not alredy reached
81 void ConditionTest::testBlocksIfNotDesiredCondition() {
82 ConditionChecker t(true);
83 t.SignalStartThread();
84 usleep(400000); // wait 400ms
85 CPPUNIT_ASSERT(t.resource == 0);
86 }
87
88 // Check if Condition class blocks until desired condition is reached
89 void ConditionTest::testBlocksUntilDesiredCondition() {
90 ConditionChecker checker(true); // let that thread wait until condition equals 'true'
91 ConditionSetter setter(&checker.condition, true); // let this thread set the condition to 'true'
92 checker.SignalStartThread();
93 usleep(50000); // wait 50ms
94 CPPUNIT_ASSERT(checker.resource == 0); // check if 'checker' thread has not passed the WaitAndUnlockIf() point yet
95 setter.SignalStartThread();
96 usleep(100000); // wait 100ms
97 CPPUNIT_ASSERT(checker.resource == 1); // check if 'checker' thread passed the WaitAndUnlockIf() point
98 }
99
100 // Check if the WaitIf() call blocks concurrent threads until the first WaitIf() caller calls Unlock()
101 void ConditionTest::testWaitIFBlocksConcurrentThread() {
102 // if the following three tests fail, then it doesn't make sense to continue with the actual one here
103 testDoesntBlockOnDesiredCondtion();
104 testBlocksIfNotDesiredCondition();
105 testBlocksUntilDesiredCondition();
106
107 // actual new test
108 ConditionCheckerLocking checker1(false);
109 ConditionCheckerLocking checker2(false);
110 checker1.SignalStartThread();
111 usleep(200000); // wait 200ms
112 CPPUNIT_ASSERT(checker1.resource == 1);
113 checker2.SignalStartThread();
114 usleep(200000); // wait 200ms
115 CPPUNIT_ASSERT(checker2.resource == 0); // check if condition locked by 'checker1'
116
117 // now order 'checker1' thread to Unlock() the condition again
118 checker1.doUnlock = true;
119 usleep(200000); // wait 200ms
120 CPPUNIT_ASSERT(checker2.resource == 1); // check if condition was unlocked by 'checker1'
121 }

  ViewVC Help
Powered by ViewVC