jack2/tests/testAtomic.cpp

257 lines
4.8 KiB
C++

/*
Copyright (C) 2004-2008 Grame
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include <iostream>
#include <unistd.h>
#include "JackAtomicState.h"
#include "JackPosixThread.h"
using namespace Jack;
#define SIZE 1024
struct TestState {
long fTable[SIZE];
long fReadCounter;
long fWriteCounter;
TestState()
{
for (int i = 0; i < SIZE; i++) {
fTable[i] = 0;
}
fReadCounter = 0;
fWriteCounter = 0;
}
virtual ~TestState()
{}
void Write()
{
fWriteCounter++;
for (int i = 0; i < SIZE; i++) {
fTable[i] = fTable[i] + 10;
}
}
bool Read()
{
int val = fTable[0];
fReadCounter++;
for (int i = 0; i < SIZE; i++) {
if (fTable[i] != val) {
printf("Read error fReadCounter %ld, i %ld, curVal %ld, oldVal %ld\n", fReadCounter, i, fTable[i], val);
return false;
}
}
return true;
}
bool ReadCopy(long* result)
{
int val = fTable[0];
fReadCounter++;
for (int i = 0; i < SIZE; i++) {
result[i] = fTable[i];
if (fTable[i] != val) {
//printf("ReadCopy error fReadCounter %ld, i %ld, curVal %ld, oldVal %ld\n", fReadCounter, i, fTable[i], val);
return false;
}
}
return true;
}
bool Check(long* result)
{
int val = result[0];
for (int i = 0; i < SIZE; i++) {
if (result[i] != val) {
printf("Check error fReadCounter %ld, i %ld, curVal %ld, oldVal %ld\n", fReadCounter, i, fTable[i], val);
return false;
}
}
return true;
}
int GetVal()
{
return fTable[10];
}
};
/*!
\brief The state wrapped with the 2 state atomic class.
*/
class TestStateUser : public JackAtomicState<TestState> {
public:
TestStateUser(){}
virtual ~TestStateUser(){}
void TestWriteMethod()
{
TestState* state = WriteNextStateStart();
state->Write();
state->Write();
state->Write();
WriteNextStateStop();
}
void TestReadMethod()
{
TestState* state;
int fCount = 0;
long result[SIZE];
UInt16 cur_index;
UInt16 next_index;
do {
cur_index = GetCurrentIndex();
fCount++;
state = ReadCurrentState();
bool res = state->ReadCopy(result);
next_index = GetCurrentIndex();
if (!res)
printf("TestReadMethod fCount %ld cur %ld next %ld\n", fCount, cur_index, next_index);
}while (cur_index != next_index);
state->Check(result);
}
void TestReadRTMethod1()
{
TestState* state = TrySwitchState();
bool res = state->Read();
}
void TestReadRTMethod2()
{
TestState* state = ReadCurrentState();
state->Read();
}
};
/*!
\brief Base class for reader/writer threads.
*/
struct TestThread : public JackRunnableInterface {
JackPosixThread* fThread;
TestStateUser* fObject;
TestThread(TestStateUser* state):fObject(state)
{
fThread = new JackPosixThread(this);
int res = fThread->Start();
}
virtual ~TestThread()
{
fThread->Kill();
delete fThread;
}
};
/*!
\brief "Real-time" reader thread.
*/
struct RTReaderThread : public TestThread {
RTReaderThread(TestStateUser* state):TestThread(state)
{}
bool Execute()
{
fObject->TestReadRTMethod1();
for (int i = 0; i < 5; i++) {
fObject->TestReadRTMethod2();
}
usleep(50);
return true;
}
};
/*!
\brief Non "Real-time" reader thread.
*/
struct ReaderThread : public TestThread {
ReaderThread(TestStateUser* state):TestThread(state)
{}
bool Execute()
{
fObject->TestReadMethod();
usleep(56);
return true;
}
};
/*!
\brief Writer thread.
*/
struct WriterThread : public TestThread {
WriterThread(TestStateUser* state):TestThread(state)
{}
bool Execute()
{
fObject->TestWriteMethod();
usleep(75);
return true;
}
};
int main(int argc, char * const argv[])
{
char c;
printf("Test concurrent access to a TestState data structure protected with the 2 state JackAtomicState class\n");
TestStateUser fObject;
WriterThread writer(&fObject);
RTReaderThread readerRT1(&fObject);
ReaderThread reader1(&fObject);
/*
ReaderThread reader2(&fObject);
ReaderThread reader3(&fObject);
ReaderThread reader4(&fObject);
ReaderThread reader5(&fObject);
ReaderThread reader6(&fObject);
*/
while ((c = getchar()) != 'q') {}
return 1;
}