git-svn-id: http://subversion.jackaudio.org/jack/jack2/trunk/jackmp@2391 0c269be4-1314-0410-8aa9-9f06e86f4224tags/1.90
| @@ -20,10 +20,14 @@ Fernando Lopez-Lezcano | |||||
| Jackdmp changes log | Jackdmp changes log | ||||
| --------------------------- | --------------------------- | ||||
| 2008-05-30 Stephane Letz <letz@grame.fr> | |||||
| * Avoid using Terminate when "quitting" in RT thread. Cleanup JackEngineInterface. | |||||
| 2008-05-29 Stephane Letz <letz@grame.fr> | 2008-05-29 Stephane Letz <letz@grame.fr> | ||||
| * Tim Blechmann patch for JackPosixSemaphore (still to test...). | * Tim Blechmann patch for JackPosixSemaphore (still to test...). | ||||
| * Correct JackWinThread::Terminate. | |||||
| * Correct JackWinThread::Terminate. | |||||
| 2008-05-28 Stephane Letz <letz@grame.fr> | 2008-05-28 Stephane Letz <letz@grame.fr> | ||||
| @@ -347,7 +347,7 @@ bool JackClient::Execute() | |||||
| if (WaitFirstSync()) | if (WaitFirstSync()) | ||||
| ExecuteThread(); | ExecuteThread(); | ||||
| } | } | ||||
| return false; // Never reached | |||||
| return false; | |||||
| } | } | ||||
| inline bool JackClient::WaitFirstSync() | inline bool JackClient::WaitFirstSync() | ||||
| @@ -366,15 +366,12 @@ inline bool JackClient::WaitFirstSync() | |||||
| } | } | ||||
| SignalSync(); | SignalSync(); | ||||
| } | } | ||||
| return false; // Never reached | |||||
| return false; | |||||
| } | } | ||||
| inline void JackClient::ExecuteThread() | inline void JackClient::ExecuteThread() | ||||
| { | { | ||||
| while (true) { | |||||
| if (Wait(CallProcessCallback()) != GetEngineControl()->fBufferSize) | |||||
| return; | |||||
| } | |||||
| while (Wait(CallProcessCallback()) == GetEngineControl()->fBufferSize); | |||||
| } | } | ||||
| jack_nframes_t JackClient::Wait(int status) | jack_nframes_t JackClient::Wait(int status) | ||||
| @@ -447,8 +444,7 @@ inline int JackClient::End() | |||||
| fThread->DropRealTime(); | fThread->DropRealTime(); | ||||
| GetClientControl()->fActive = false; | GetClientControl()->fActive = false; | ||||
| fChannel->ClientDeactivate(GetClientControl()->fRefNum, &result); | fChannel->ClientDeactivate(GetClientControl()->fRefNum, &result); | ||||
| fThread->Terminate(); | |||||
| return 0; // Never reached | |||||
| return 0; | |||||
| } | } | ||||
| inline int JackClient::Error() | inline int JackClient::Error() | ||||
| @@ -460,8 +456,7 @@ inline int JackClient::Error() | |||||
| GetClientControl()->fActive = false; | GetClientControl()->fActive = false; | ||||
| fChannel->ClientDeactivate(GetClientControl()->fRefNum, &result); | fChannel->ClientDeactivate(GetClientControl()->fRefNum, &result); | ||||
| ShutDown(); | ShutDown(); | ||||
| fThread->Terminate(); | |||||
| return 0; // Never reached | |||||
| return 0; | |||||
| } | } | ||||
| //----------------- | //----------------- | ||||
| @@ -85,10 +85,8 @@ class JackEngineInterface | |||||
| virtual void NotifyGraphReorder() = 0; | virtual void NotifyGraphReorder() = 0; | ||||
| virtual void NotifyBufferSize(jack_nframes_t nframes) = 0; | virtual void NotifyBufferSize(jack_nframes_t nframes) = 0; | ||||
| virtual void NotifyFreewheel(bool onoff) = 0; | virtual void NotifyFreewheel(bool onoff) = 0; | ||||
| virtual void NotifyPortRegistation(jack_port_id_t port_index, bool onoff) = 0; | |||||
| virtual void NotifyPortConnect(jack_port_id_t src, jack_port_id_t dst, bool onoff) = 0; | |||||
| virtual void NotifyActivate(int refnum) = 0; | |||||
| }; | |||||
| }; | |||||
| /*! | /*! | ||||
| \brief Engine description. | \brief Engine description. | ||||
| @@ -123,6 +121,9 @@ class JackEngine | |||||
| void NotifyClient(int refnum, int event, int sync, int value1, int value2); | void NotifyClient(int refnum, int event, int sync, int value1, int value2); | ||||
| void NotifyClients(int event, int sync, int value1, int value2); | void NotifyClients(int event, int sync, int value1, int value2); | ||||
| void NotifyPortRegistation(jack_port_id_t port_index, bool onoff); | |||||
| void NotifyPortConnect(jack_port_id_t src, jack_port_id_t dst, bool onoff); | |||||
| void NotifyActivate(int refnum); | |||||
| public: | public: | ||||
| @@ -169,9 +170,6 @@ class JackEngine | |||||
| void NotifyGraphReorder(); | void NotifyGraphReorder(); | ||||
| void NotifyBufferSize(jack_nframes_t nframes); | void NotifyBufferSize(jack_nframes_t nframes); | ||||
| void NotifyFreewheel(bool onoff); | void NotifyFreewheel(bool onoff); | ||||
| void NotifyPortRegistation(jack_port_id_t port_index, bool onoff); | |||||
| void NotifyPortConnect(jack_port_id_t src, jack_port_id_t dst, bool onoff); | |||||
| void NotifyActivate(int refnum); | |||||
| }; | }; | ||||
| @@ -179,22 +179,7 @@ class JackLockedEngine : public JackEngineInterface, public JackLockAble | |||||
| JackLock lock(this); | JackLock lock(this); | ||||
| fEngine.NotifyFreewheel(onoff); | fEngine.NotifyFreewheel(onoff); | ||||
| } | } | ||||
| void NotifyPortRegistation(jack_port_id_t port_index, bool onoff) | |||||
| { | |||||
| JackLock lock(this); | |||||
| fEngine.NotifyPortRegistation(port_index, onoff); | |||||
| } | |||||
| void NotifyPortConnect(jack_port_id_t src, jack_port_id_t dst, bool onoff) | |||||
| { | |||||
| JackLock lock(this); | |||||
| fEngine.NotifyPortConnect(src, dst, onoff); | |||||
| } | |||||
| void NotifyActivate(int refnum) | |||||
| { | |||||
| JackLock lock(this); | |||||
| fEngine.NotifyActivate(refnum); | |||||
| } | |||||
| int GetClientPID(const char* name) | int GetClientPID(const char* name) | ||||
| { | { | ||||
| JackLock lock(this); | JackLock lock(this); | ||||
| @@ -158,7 +158,7 @@ int JackServer::InternalClientLoad(const char* client_name, const char* so_name, | |||||
| *status = 0; | *status = 0; | ||||
| JackLoadableInternalClient* client = new JackLoadableInternalClient(fInstance, GetSynchroTable(), so_name, objet_data); | JackLoadableInternalClient* client = new JackLoadableInternalClient(fInstance, GetSynchroTable(), so_name, objet_data); | ||||
| assert(client); | assert(client); | ||||
| int res = client->Open("unused", client_name, (jack_options_t)options, (jack_status_t*)status); | |||||
| int res = client->Open(JACK_DEFAULT_SERVER_NAME, client_name, (jack_options_t)options, (jack_status_t*)status); | |||||
| if (res < 0) { | if (res < 0) { | ||||
| delete client; | delete client; | ||||
| *int_ref = 0; | *int_ref = 0; | ||||
| @@ -69,12 +69,21 @@ static void* jack_thread(void *arg) | |||||
| jack_client_t* client = (jack_client_t*) arg; | jack_client_t* client = (jack_client_t*) arg; | ||||
| while (1) { | while (1) { | ||||
| jack_nframes_t frames = jack_cycle_wait (client); | jack_nframes_t frames = jack_cycle_wait (client); | ||||
| int status = _process(frames); | int status = _process(frames); | ||||
| jack_cycle_signal (client, status); | jack_cycle_signal (client, status); | ||||
| // possibly do something else after signaling next clients in the graph | |||||
| /* | |||||
| Possibly do something else after signaling next clients in the graph | |||||
| */ | |||||
| /* End condition */ | |||||
| if (status != 0) | |||||
| return 0; | |||||
| } | } | ||||
| /* not reached*/ | |||||
| return 0; | return 0; | ||||
| } | } | ||||
| @@ -808,7 +808,7 @@ | |||||
| isa = PBXContainerItemProxy; | isa = PBXContainerItemProxy; | ||||
| containerPortal = 08FB7793FE84155DC02AAC07 /* Project object */; | containerPortal = 08FB7793FE84155DC02AAC07 /* Project object */; | ||||
| proxyType = 1; | proxyType = 1; | ||||
| remoteGlobalIDString = 4BFA5E8B0DEC4D9C00FA4CDB /* testMutex Universal */; | |||||
| remoteGlobalIDString = 4BFA5E8B0DEC4D9C00FA4CDB; | |||||
| remoteInfo = "testMutex Universal"; | remoteInfo = "testMutex Universal"; | ||||
| }; | }; | ||||
| 4B699DB3097D421700A18468 /* PBXContainerItemProxy */ = { | 4B699DB3097D421700A18468 /* PBXContainerItemProxy */ = { | ||||
| @@ -2029,8 +2029,8 @@ | |||||
| 4BA550FB05E2420000569492 /* Engine */ = { | 4BA550FB05E2420000569492 /* Engine */ = { | ||||
| isa = PBXGroup; | isa = PBXGroup; | ||||
| children = ( | children = ( | ||||
| 4B5F253D0DEE9B8F0041E486 /* JackLockedEngine.h */, | |||||
| 4B168CA3076A5319005B2802 /* MIG_RPC */, | 4B168CA3076A5319005B2802 /* MIG_RPC */, | ||||
| 4B5F253D0DEE9B8F0041E486 /* JackLockedEngine.h */, | |||||
| 4BF8D2130834F02800C94B91 /* JackEngine.h */, | 4BF8D2130834F02800C94B91 /* JackEngine.h */, | ||||
| 4BF8D2140834F02800C94B91 /* JackEngine.cpp */, | 4BF8D2140834F02800C94B91 /* JackEngine.cpp */, | ||||
| 4BF8FB0E08AC88EF00D1A344 /* JackFrameTimer.h */, | 4BF8FB0E08AC88EF00D1A344 /* JackFrameTimer.h */, | ||||
| @@ -29,67 +29,192 @@ | |||||
| #include "JackPosixThread.h" | #include "JackPosixThread.h" | ||||
| #include "JackMutex.h" | #include "JackMutex.h" | ||||
| #include <jack/thread.h> | |||||
| using namespace Jack; | using namespace Jack; | ||||
| static void CleanupHandler(void * arg) | |||||
| { | |||||
| JackLockAble* locked = (JackLockAble*)arg; | |||||
| printf("CleanupHandler locked %x \n", locked); | |||||
| locked->Unlock(); | |||||
| } | |||||
| struct LockedObject : public JackLockAble { | struct LockedObject : public JackLockAble { | ||||
| JackThread* fThread; | |||||
| int fCount; | int fCount; | ||||
| LockedObject():fCount(0) | LockedObject():fCount(0) | ||||
| {} | {} | ||||
| virtual ~LockedObject() | virtual ~LockedObject() | ||||
| { | |||||
| fThread->Kill(); | |||||
| delete fThread; | |||||
| } | |||||
| {} | |||||
| /* | |||||
| void LockedMethod1() | void LockedMethod1() | ||||
| { | { | ||||
| JackLock lock(this); | JackLock lock(this); | ||||
| fCount++; | fCount++; | ||||
| printf("LockedMethod1 self %x fCount %d\n", pthread_self(), fCount); | printf("LockedMethod1 self %x fCount %d\n", pthread_self(), fCount); | ||||
| } | |||||
| if (fCount >= 1000) { | |||||
| printf("Terminate self %x\n", pthread_self()); | |||||
| pthread_exit(NULL); | |||||
| } | |||||
| } | |||||
| void LockedMethod2() | void LockedMethod2() | ||||
| { | { | ||||
| JackLock lock(this); | JackLock lock(this); | ||||
| fCount--; | |||||
| fCount++; | |||||
| printf("LockedMethod2 self %x fCount %d\n", pthread_self(), fCount); | printf("LockedMethod2 self %x fCount %d\n", pthread_self(), fCount); | ||||
| if (fCount >= 1500) { | |||||
| printf("Terminate self %x\n", pthread_self()); | |||||
| pthread_exit(NULL); | |||||
| } | |||||
| } | } | ||||
| void LockedMethod3() | void LockedMethod3() | ||||
| { | { | ||||
| JackLock lock(this); | JackLock lock(this); | ||||
| fCount--; | |||||
| fCount++; | |||||
| printf("LockedMethod3 self %x fCount %d\n", pthread_self(), fCount); | printf("LockedMethod3 self %x fCount %d\n", pthread_self(), fCount); | ||||
| if (fCount >= 3000) { | |||||
| printf("Terminate self %x\n", pthread_self()); | |||||
| pthread_exit(NULL); | |||||
| } | |||||
| } | |||||
| */ | |||||
| void LockedMethod1() | |||||
| { | |||||
| pthread_cleanup_push(CleanupHandler, this); | |||||
| Lock(); | |||||
| fCount++; | |||||
| //printf("LockedMethod1 self %x fCount %d\n", pthread_self(), fCount); | |||||
| if (fCount >= 1000) { | |||||
| printf("Terminate self = %x count = %d\n", pthread_self(), fCount); | |||||
| pthread_exit(NULL); | |||||
| } | |||||
| Unlock(); | |||||
| pthread_cleanup_pop(0); | |||||
| } | |||||
| void LockedMethod2() | |||||
| { | |||||
| pthread_cleanup_push(CleanupHandler, this); | |||||
| Lock(); | |||||
| fCount++; | |||||
| //printf("LockedMethod2 self %x fCount %d\n", pthread_self(), fCount); | |||||
| if (fCount >= 1500) { | |||||
| printf("Terminate self = %x count = %d\n", pthread_self(), fCount); | |||||
| pthread_exit(NULL); | |||||
| } | |||||
| Unlock(); | |||||
| pthread_cleanup_pop(0); | |||||
| } | } | ||||
| void LockedMethod3() | |||||
| { | |||||
| pthread_cleanup_push(CleanupHandler, this); | |||||
| Lock(); | |||||
| fCount++; | |||||
| //printf("LockedMethod3 self %x fCount %d\n", pthread_self(), fCount); | |||||
| if (fCount >= 3000) { | |||||
| printf("Terminate self = %x count = %d\n", pthread_self(), fCount); | |||||
| pthread_exit(NULL); | |||||
| } | |||||
| Unlock(); | |||||
| pthread_cleanup_pop(0); | |||||
| } | |||||
| }; | }; | ||||
| struct TestThread : public JackRunnableInterface { | struct TestThread : public JackRunnableInterface { | ||||
| JackThread* fThread; | |||||
| JackMachThread* fThread; | |||||
| LockedObject* fObject; | LockedObject* fObject; | ||||
| int fNum; | int fNum; | ||||
| TestThread(LockedObject* obj, int num) | TestThread(LockedObject* obj, int num) | ||||
| { | { | ||||
| printf("TestThread\n"); | |||||
| fThread = new JackMachThread(this); | fThread = new JackMachThread(this); | ||||
| fObject = obj; | fObject = obj; | ||||
| fNum = num; | fNum = num; | ||||
| fThread->StartSync(); | fThread->StartSync(); | ||||
| } | |||||
| } | |||||
| virtual ~TestThread() | virtual ~TestThread() | ||||
| { | { | ||||
| printf("DELETE %x\n", fThread); | |||||
| fThread->Kill(); | fThread->Kill(); | ||||
| delete fThread; | delete fThread; | ||||
| } | } | ||||
| bool Execute() | |||||
| { | |||||
| //printf("TestThread Execute\n"); | |||||
| switch (fNum) { | |||||
| case 1: | |||||
| fObject->LockedMethod1(); | |||||
| /* | |||||
| if (fObject->fCount >= 500) { | |||||
| printf("Terminate self %x\n", pthread_self()); | |||||
| fThread->Terminate(); | |||||
| } | |||||
| */ | |||||
| break; | |||||
| case 2: | |||||
| fObject->LockedMethod2(); | |||||
| /* | |||||
| if (fObject->fCount >= 1500) { | |||||
| printf("Terminate self %x\n", pthread_self()); | |||||
| fThread->Terminate(); | |||||
| } | |||||
| */ | |||||
| break; | |||||
| case 3: | |||||
| fObject->LockedMethod3(); | |||||
| /* | |||||
| if (fObject->fCount >= 2000) { | |||||
| printf("Terminate self %x\n", pthread_self()); | |||||
| fThread->Terminate(); | |||||
| } | |||||
| */ | |||||
| break; | |||||
| }; | |||||
| //usleep(fNum * 1000); | |||||
| return true; | |||||
| } | |||||
| }; | |||||
| static void* TestThread1_Execute(void* arg); | |||||
| struct TestThread1 : public JackRunnableInterface { | |||||
| pthread_t fThread; | |||||
| LockedObject* fObject; | |||||
| int fNum; | |||||
| TestThread1(LockedObject* obj, int num) | |||||
| { | |||||
| if (jack_client_create_thread(NULL, &fThread, 0, 0, TestThread1_Execute, this)) | |||||
| jack_error( "Can't create the network manager control thread." ); | |||||
| fObject = obj; | |||||
| fNum = num; | |||||
| } | |||||
| virtual ~TestThread1() | |||||
| {} | |||||
| bool Execute() | bool Execute() | ||||
| { | { | ||||
| printf("TestThread Execute\n"); | printf("TestThread Execute\n"); | ||||
| @@ -108,21 +233,76 @@ struct TestThread : public JackRunnableInterface { | |||||
| break; | break; | ||||
| }; | }; | ||||
| usleep(fNum * 1000); | |||||
| //usleep(fNum * 1000); | |||||
| return true; | return true; | ||||
| } | } | ||||
| }; | }; | ||||
| static void* TestThread1_Execute(void* arg) | |||||
| { | |||||
| TestThread1* obj = (TestThread1*)arg; | |||||
| while (true) { | |||||
| //printf("TestThread Execute\n"); | |||||
| switch (obj->fNum) { | |||||
| case 1: | |||||
| obj->fObject->LockedMethod1(); | |||||
| break; | |||||
| case 2: | |||||
| obj->fObject->LockedMethod2(); | |||||
| break; | |||||
| case 3: | |||||
| obj->fObject->LockedMethod3(); | |||||
| break; | |||||
| }; | |||||
| //usleep(obj->fNum * 1000); | |||||
| } | |||||
| return 0; | |||||
| } | |||||
| int main (int argc, char * const argv[]) | int main (int argc, char * const argv[]) | ||||
| { | { | ||||
| char c; | char c; | ||||
| LockedObject obj; | LockedObject obj; | ||||
| TestThread th1(&obj, 1); | TestThread th1(&obj, 1); | ||||
| TestThread th2(&obj, 2); | TestThread th2(&obj, 2); | ||||
| TestThread th3(&obj, 3); | TestThread th3(&obj, 3); | ||||
| /* | |||||
| LockedObject obj; | |||||
| TestThread1 th1(&obj, 1); | |||||
| TestThread th2(&obj, 2); | |||||
| TestThread th3(&obj, 3); | |||||
| */ | |||||
| while ((c = getchar()) != 'q') {} | |||||
| /* | |||||
| while ((c = getchar()) != 'q') { | |||||
| } | |||||
| */ | |||||
| while (true) { | |||||
| usleep(1000); | |||||
| th1.fThread->Kill(); | |||||
| } | |||||
| /* | |||||
| th1.fThread->Kill(); | |||||
| th2.fThread->Kill(); | |||||
| th3.fThread->Kill(); | |||||
| while (true) { | |||||
| //usleep(100000); | |||||
| th1.fThread->Kill(); | |||||
| } | |||||
| */ | |||||
| } | } | ||||