/* 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 #include #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 { 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; }