257 lines
4.8 KiB
C++
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;
|
|
}
|
|
|
|
|